From 21d28ff3022ba7d7db389f7bc8793e1075812672 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 14 Jun 2023 17:12:26 +0200 Subject: [PATCH 01/67] initail commit --- brownie/addresses.py | 5 +++++ brownie/playingAround.py | 15 +++++++++++++++ brownie/world.py | 6 ++++++ dapp/abis/Flipper.json | 4 ++-- 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 brownie/playingAround.py diff --git a/brownie/addresses.py b/brownie/addresses.py index b9664cfc81..bb864ac329 100644 --- a/brownie/addresses.py +++ b/brownie/addresses.py @@ -56,6 +56,11 @@ BUSD = '0x4Fabb145d64652a948d72533023f6E7A623C7C53' WETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' STETH = '0xae7ab96520de3a18e5e111b5eaab095312d7fe84' +WSTETH = '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0' +SFRXETH = '0xac3E018457B222d93114458476f3E3416Abbe38F' +FRXETH = '0x5e8422345238f34275888049021821e8e08caa1f' +RETH = '0xae78736Cd615f374D3085123A210448E74Fc6393' + THREEPOOL_LP = '0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490' OUSD_METAPOOL = '0x87650D7bbfC3A9F10587d7778206671719d9910D' diff --git a/brownie/playingAround.py b/brownie/playingAround.py new file mode 100644 index 0000000000..2392feb8cf --- /dev/null +++ b/brownie/playingAround.py @@ -0,0 +1,15 @@ +from world import * + +# pool factory +#https://etherscan.io/address/0xfADa0f4547AB2de89D1304A668C39B3E09Aa7c76#code + +pool_id = "0x5aee1e99fe86960377de9f88689616916d5dcabe000000000000000000000467" +ba_vault=Contract.from_explorer("0xBA12222222228d8Ba445958a75a0704d566BF2C8") +ba_batch_relayer = Contract.from_explorer("0xf77018c0d817dA22caDbDf504C00c0d32cE1e5C2") + +bpt = "0x5aEe1e99fE86960377DE9f88689616916D5DcaBe" +reth.approve(ba_vault, 10**50, {"from": vault_oeth_core}) + +# 1 stands for EXACT_TOKENS_IN_FOR_BPT_OUT +join_request = ([bpt, wsteth, sfrxeth, reth], [0, 0, 0, 10**18], 1 , False) +ba_vault.joinPool(pool_id, vault_oeth_core, vault_oeth_core, join_request, {"from": vault_oeth_core}) diff --git a/brownie/world.py b/brownie/world.py index b17339f09e..abccbcb00a 100644 --- a/brownie/world.py +++ b/brownie/world.py @@ -33,6 +33,12 @@ def load_contract(name, address): usdt = load_contract('usdt', USDT) usdc = load_contract('usdc', USDC) dai = load_contract('dai', DAI) +steth = load_contract('ERC20', STETH) +wsteth = load_contract('ERC20', WSTETH) +sfrxeth = load_contract('ERC20', SFRXETH) +frxeth = load_contract('ERC20', FRXETH) +reth = load_contract('ERC20', RETH) + flipper = load_contract('flipper', FLIPPER) #buyback = load_contract('buyback', BUYBACK) buyback = load_contract('buyback', BUYBACK_2) diff --git a/dapp/abis/Flipper.json b/dapp/abis/Flipper.json index 7d064d83af..ae3a548c9d 100644 --- a/dapp/abis/Flipper.json +++ b/dapp/abis/Flipper.json @@ -224,8 +224,8 @@ "type": "function" } ], - "bytecode": "0x6101006040523480156200001257600080fd5b50604051620018ba380380620018ba833981016040819052620000359162000132565b6200004d336000805160206200189a83398151915255565b6000805160206200189a833981519152546040516001600160a01b03909116906000907fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a908290a36001600160a01b038416620000a957600080fd5b6001600160a01b038316620000bd57600080fd5b6001600160a01b038216620000d157600080fd5b6001600160a01b038116620000e557600080fd5b6001600160601b0319606094851b811660805292841b831660a05290831b821660c05290911b1660e0526200018f565b80516001600160a01b03811681146200012d57600080fd5b919050565b600080600080608085870312156200014957600080fd5b620001548562000115565b9350620001646020860162000115565b9250620001746040860162000115565b9150620001846060860162000115565b905092959194509250565b60805160601c60a05160601c60c05160601c60e05160601c61165c6200023e6000396000818161021d015281816107ed0152818161087b0152610d920152600081816108d00152818161095c01528181610b1a0152610c370152600081816102bd015281816104b40152818161070c0152818161079801528181610aad01528181610e3a01526110260152600081816103cb0152818161062b015281816106b701526109d0015261165c6000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063bfc11ffd1161008c578063cb93905311610066578063cb93905314610182578063d38bfff414610195578063f3fef3a3146101a8578063f51b0fd4146101bb57600080fd5b8063bfc11ffd14610144578063c6b6816914610157578063c7af33521461016a57600080fd5b80630c340a24146100d457806335aa0b96146100f95780635981c7461461010e5780635d36b19014610121578063853828b6146101295780638a095a0f14610131575b600080fd5b6100dc6101c3565b6040516001600160a01b0390911681526020015b60405180910390f35b61010c610107366004611486565b6101e0565b005b61010c61011c366004611486565b61038a565b61010c6104eb565b61010c610591565b61010c61013f366004611486565b61098a565b61010c610152366004611486565b610ae6565b61010c610165366004611486565b610c03565b610172610d2d565b60405190151581526020016100f0565b61010c610190366004611486565b610d5e565b61010c6101a336600461141f565b610e75565b61010c6101b636600461143a565b610f19565b61010c610fb8565b60006101db6000805160206116078339815191525490565b905090565b69054b40b1f852bda000008111156102135760405162461bcd60e51b815260040161020a90611562565b60405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd333061025364e8d4a51000866115b4565b6040518463ffffffff1660e01b8152600401610271939291906114d4565b600060405180830381600087803b15801561028b57600080fd5b505af115801561029f573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb91506044015b602060405180830381600087803b15801561030c57600080fd5b505af1158015610320573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103449190611464565b6103875760405162461bcd60e51b815260206004820152601460248201527313d554d1081d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b50565b69054b40b1f852bda000008111156103b45760405162461bcd60e51b815260040161020a90611562565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90610404903390309086906004016114d4565b602060405180830381600087803b15801561041e57600080fd5b505af1158015610432573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104569190611464565b6104985760405162461bcd60e51b8152602060048201526013602482015272111052481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161020a565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016102f2565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b0316146105865760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b606482015260840161020a565b61058f3361109f565b565b610599610d2d565b6105b55760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535805460028114156105f95760405162461bcd60e51b815260040161020a9061158c565b600282556106de6106166000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561067557600080fd5b505afa158015610689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ad919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6107bf6106f76000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561075657600080fd5b505afa15801561076a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078e919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6108a26107d86000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381600087803b15801561083957600080fd5b505af115801561084d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610871919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6109836108bb6000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561091a57600080fd5b505afa15801561092e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610952919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b5060019055565b69054b40b1f852bda000008111156109b45760405162461bcd60e51b815260040161020a90611562565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90604401602060405180830381600087803b158015610a1c57600080fd5b505af1158015610a30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a549190611464565b610a965760405162461bcd60e51b8152602060048201526013602482015272111052481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161020a565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906102f2903390309086906004016114d4565b69054b40b1f852bda00000811115610b105760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd3330610b5064e8d4a51000866115b4565b6040518463ffffffff1660e01b8152600401610b6e939291906114d4565b602060405180830381600087803b158015610b8857600080fd5b505af1158015610b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc09190611464565b6104985760405162461bcd60e51b81526020600482015260146024820152731554d110c81d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b69054b40b1f852bda00000811115610c2d5760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610c6c64e8d4a51000856115b4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b158015610cb257600080fd5b505af1158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cea9190611464565b610a965760405162461bcd60e51b81526020600482015260146024820152731554d110c81d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b6000610d456000805160206116078339815191525490565b6001600160a01b0316336001600160a01b031614905090565b69054b40b1f852bda00000811115610d885760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610dc764e8d4a51000856115b4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610e0d57600080fd5b505af1158015610e21573d6000803e3d6000fd5b50506040516323b872dd60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506323b872dd91506102f2903390309086906004016114d4565b610e7d610d2d565b610e995760405162461bcd60e51b815260040161020a9061152b565b610ec1817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b0316610ee16000805160206116078339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b610f21610d2d565b610f3d5760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac453580546002811415610f815760405162461bcd60e51b815260040161020a9061158c565b60028255610faf610f9e6000805160206116078339815191525490565b6001600160a01b0386169085611160565b50600190555050565b610fc0610d2d565b610fdc5760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535805460028114156110205760405162461bcd60e51b815260040161020a9061158c565b600282557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f51b0fd46040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561107f57600080fd5b505af1158015611093573d6000803e3d6000fd5b50505050600182555050565b6001600160a01b0381166110f55760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015260640161020a565b806001600160a01b03166111156000805160206116078339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36103878160008051602061160783398151915255565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526111b29084906111b7565b505050565b600061120c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112899092919063ffffffff16565b8051909150156111b2578080602001905181019061122a9190611464565b6111b25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161020a565b606061129884846000856112a2565b90505b9392505050565b6060824710156113035760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161020a565b843b6113515760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161020a565b600080866001600160a01b0316858760405161136d91906114b8565b60006040518083038185875af1925050503d80600081146113aa576040519150601f19603f3d011682016040523d82523d6000602084013e6113af565b606091505b50915091506113bf8282866113ca565b979650505050505050565b606083156113d957508161129b565b8251156113e95782518084602001fd5b8160405162461bcd60e51b815260040161020a91906114f8565b80356001600160a01b038116811461141a57600080fd5b919050565b60006020828403121561143157600080fd5b61129b82611403565b6000806040838503121561144d57600080fd5b61145683611403565b946020939093013593505050565b60006020828403121561147657600080fd5b8151801515811461129b57600080fd5b60006020828403121561149857600080fd5b5035919050565b6000602082840312156114b157600080fd5b5051919050565b600082516114ca8184602087016115d6565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208152600082518060208401526115178160408501602087016115d6565b601f01601f19169190910160400192915050565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b60208082526010908201526f416d6f756e7420746f6f206c6172676560801b604082015260600190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b6000826115d157634e487b7160e01b600052601260045260246000fd5b500490565b60005b838110156115f15781810151838201526020016115d9565b83811115611600576000848401525b5050505056fe7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa2646970667358221220de5427febdef50e4707714b2e0dfb29a3f79546b9c8b263b0745d60c503c00ee64736f6c634300080700337bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063bfc11ffd1161008c578063cb93905311610066578063cb93905314610182578063d38bfff414610195578063f3fef3a3146101a8578063f51b0fd4146101bb57600080fd5b8063bfc11ffd14610144578063c6b6816914610157578063c7af33521461016a57600080fd5b80630c340a24146100d457806335aa0b96146100f95780635981c7461461010e5780635d36b19014610121578063853828b6146101295780638a095a0f14610131575b600080fd5b6100dc6101c3565b6040516001600160a01b0390911681526020015b60405180910390f35b61010c610107366004611486565b6101e0565b005b61010c61011c366004611486565b61038a565b61010c6104eb565b61010c610591565b61010c61013f366004611486565b61098a565b61010c610152366004611486565b610ae6565b61010c610165366004611486565b610c03565b610172610d2d565b60405190151581526020016100f0565b61010c610190366004611486565b610d5e565b61010c6101a336600461141f565b610e75565b61010c6101b636600461143a565b610f19565b61010c610fb8565b60006101db6000805160206116078339815191525490565b905090565b69054b40b1f852bda000008111156102135760405162461bcd60e51b815260040161020a90611562565b60405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd333061025364e8d4a51000866115b4565b6040518463ffffffff1660e01b8152600401610271939291906114d4565b600060405180830381600087803b15801561028b57600080fd5b505af115801561029f573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb91506044015b602060405180830381600087803b15801561030c57600080fd5b505af1158015610320573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103449190611464565b6103875760405162461bcd60e51b815260206004820152601460248201527313d554d1081d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b50565b69054b40b1f852bda000008111156103b45760405162461bcd60e51b815260040161020a90611562565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90610404903390309086906004016114d4565b602060405180830381600087803b15801561041e57600080fd5b505af1158015610432573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104569190611464565b6104985760405162461bcd60e51b8152602060048201526013602482015272111052481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161020a565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016102f2565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b0316146105865760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b606482015260840161020a565b61058f3361109f565b565b610599610d2d565b6105b55760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535805460028114156105f95760405162461bcd60e51b815260040161020a9061158c565b600282556106de6106166000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561067557600080fd5b505afa158015610689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ad919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6107bf6106f76000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561075657600080fd5b505afa15801561076a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078e919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6108a26107d86000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381600087803b15801561083957600080fd5b505af115801561084d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610871919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6109836108bb6000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561091a57600080fd5b505afa15801561092e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610952919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b5060019055565b69054b40b1f852bda000008111156109b45760405162461bcd60e51b815260040161020a90611562565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90604401602060405180830381600087803b158015610a1c57600080fd5b505af1158015610a30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a549190611464565b610a965760405162461bcd60e51b8152602060048201526013602482015272111052481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161020a565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906102f2903390309086906004016114d4565b69054b40b1f852bda00000811115610b105760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd3330610b5064e8d4a51000866115b4565b6040518463ffffffff1660e01b8152600401610b6e939291906114d4565b602060405180830381600087803b158015610b8857600080fd5b505af1158015610b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc09190611464565b6104985760405162461bcd60e51b81526020600482015260146024820152731554d110c81d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b69054b40b1f852bda00000811115610c2d5760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610c6c64e8d4a51000856115b4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b158015610cb257600080fd5b505af1158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cea9190611464565b610a965760405162461bcd60e51b81526020600482015260146024820152731554d110c81d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b6000610d456000805160206116078339815191525490565b6001600160a01b0316336001600160a01b031614905090565b69054b40b1f852bda00000811115610d885760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610dc764e8d4a51000856115b4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610e0d57600080fd5b505af1158015610e21573d6000803e3d6000fd5b50506040516323b872dd60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506323b872dd91506102f2903390309086906004016114d4565b610e7d610d2d565b610e995760405162461bcd60e51b815260040161020a9061152b565b610ec1817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b0316610ee16000805160206116078339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b610f21610d2d565b610f3d5760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac453580546002811415610f815760405162461bcd60e51b815260040161020a9061158c565b60028255610faf610f9e6000805160206116078339815191525490565b6001600160a01b0386169085611160565b50600190555050565b610fc0610d2d565b610fdc5760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535805460028114156110205760405162461bcd60e51b815260040161020a9061158c565b600282557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f51b0fd46040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561107f57600080fd5b505af1158015611093573d6000803e3d6000fd5b50505050600182555050565b6001600160a01b0381166110f55760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015260640161020a565b806001600160a01b03166111156000805160206116078339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36103878160008051602061160783398151915255565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526111b29084906111b7565b505050565b600061120c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112899092919063ffffffff16565b8051909150156111b2578080602001905181019061122a9190611464565b6111b25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161020a565b606061129884846000856112a2565b90505b9392505050565b6060824710156113035760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161020a565b843b6113515760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161020a565b600080866001600160a01b0316858760405161136d91906114b8565b60006040518083038185875af1925050503d80600081146113aa576040519150601f19603f3d011682016040523d82523d6000602084013e6113af565b606091505b50915091506113bf8282866113ca565b979650505050505050565b606083156113d957508161129b565b8251156113e95782518084602001fd5b8160405162461bcd60e51b815260040161020a91906114f8565b80356001600160a01b038116811461141a57600080fd5b919050565b60006020828403121561143157600080fd5b61129b82611403565b6000806040838503121561144d57600080fd5b61145683611403565b946020939093013593505050565b60006020828403121561147657600080fd5b8151801515811461129b57600080fd5b60006020828403121561149857600080fd5b5035919050565b6000602082840312156114b157600080fd5b5051919050565b600082516114ca8184602087016115d6565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208152600082518060208401526115178160408501602087016115d6565b601f01601f19169190910160400192915050565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b60208082526010908201526f416d6f756e7420746f6f206c6172676560801b604082015260600190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b6000826115d157634e487b7160e01b600052601260045260246000fd5b500490565b60005b838110156115f15781810151838201526020016115d9565b83811115611600576000848401525b5050505056fe7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa2646970667358221220de5427febdef50e4707714b2e0dfb29a3f79546b9c8b263b0745d60c503c00ee64736f6c63430008070033", + "bytecode": "0x6101006040523480156200001257600080fd5b50604051620018ba380380620018ba833981016040819052620000359162000132565b6200004d336000805160206200189a83398151915255565b6000805160206200189a833981519152546040516001600160a01b03909116906000907fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a908290a36001600160a01b038416620000a957600080fd5b6001600160a01b038316620000bd57600080fd5b6001600160a01b038216620000d157600080fd5b6001600160a01b038116620000e557600080fd5b6001600160601b0319606094851b811660805292841b831660a05290831b821660c05290911b1660e0526200018f565b80516001600160a01b03811681146200012d57600080fd5b919050565b600080600080608085870312156200014957600080fd5b620001548562000115565b9350620001646020860162000115565b9250620001746040860162000115565b9150620001846060860162000115565b905092959194509250565b60805160601c60a05160601c60c05160601c60e05160601c61165c6200023e6000396000818161021d015281816107ed0152818161087b0152610d920152600081816108d00152818161095c01528181610b1a0152610c370152600081816102bd015281816104b40152818161070c0152818161079801528181610aad01528181610e3a01526110260152600081816103cb0152818161062b015281816106b701526109d0015261165c6000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063bfc11ffd1161008c578063cb93905311610066578063cb93905314610182578063d38bfff414610195578063f3fef3a3146101a8578063f51b0fd4146101bb57600080fd5b8063bfc11ffd14610144578063c6b6816914610157578063c7af33521461016a57600080fd5b80630c340a24146100d457806335aa0b96146100f95780635981c7461461010e5780635d36b19014610121578063853828b6146101295780638a095a0f14610131575b600080fd5b6100dc6101c3565b6040516001600160a01b0390911681526020015b60405180910390f35b61010c610107366004611486565b6101e0565b005b61010c61011c366004611486565b61038a565b61010c6104eb565b61010c610591565b61010c61013f366004611486565b61098a565b61010c610152366004611486565b610ae6565b61010c610165366004611486565b610c03565b610172610d2d565b60405190151581526020016100f0565b61010c610190366004611486565b610d5e565b61010c6101a336600461141f565b610e75565b61010c6101b636600461143a565b610f19565b61010c610fb8565b60006101db6000805160206116078339815191525490565b905090565b69054b40b1f852bda000008111156102135760405162461bcd60e51b815260040161020a90611562565b60405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd333061025364e8d4a51000866115b4565b6040518463ffffffff1660e01b8152600401610271939291906114d4565b600060405180830381600087803b15801561028b57600080fd5b505af115801561029f573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb91506044015b602060405180830381600087803b15801561030c57600080fd5b505af1158015610320573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103449190611464565b6103875760405162461bcd60e51b815260206004820152601460248201527313d554d1081d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b50565b69054b40b1f852bda000008111156103b45760405162461bcd60e51b815260040161020a90611562565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90610404903390309086906004016114d4565b602060405180830381600087803b15801561041e57600080fd5b505af1158015610432573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104569190611464565b6104985760405162461bcd60e51b8152602060048201526013602482015272111052481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161020a565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016102f2565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b0316146105865760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b606482015260840161020a565b61058f3361109f565b565b610599610d2d565b6105b55760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535805460028114156105f95760405162461bcd60e51b815260040161020a9061158c565b600282556106de6106166000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561067557600080fd5b505afa158015610689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ad919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6107bf6106f76000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561075657600080fd5b505afa15801561076a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078e919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6108a26107d86000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381600087803b15801561083957600080fd5b505af115801561084d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610871919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6109836108bb6000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561091a57600080fd5b505afa15801561092e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610952919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b5060019055565b69054b40b1f852bda000008111156109b45760405162461bcd60e51b815260040161020a90611562565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90604401602060405180830381600087803b158015610a1c57600080fd5b505af1158015610a30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a549190611464565b610a965760405162461bcd60e51b8152602060048201526013602482015272111052481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161020a565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906102f2903390309086906004016114d4565b69054b40b1f852bda00000811115610b105760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd3330610b5064e8d4a51000866115b4565b6040518463ffffffff1660e01b8152600401610b6e939291906114d4565b602060405180830381600087803b158015610b8857600080fd5b505af1158015610b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc09190611464565b6104985760405162461bcd60e51b81526020600482015260146024820152731554d110c81d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b69054b40b1f852bda00000811115610c2d5760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610c6c64e8d4a51000856115b4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b158015610cb257600080fd5b505af1158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cea9190611464565b610a965760405162461bcd60e51b81526020600482015260146024820152731554d110c81d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b6000610d456000805160206116078339815191525490565b6001600160a01b0316336001600160a01b031614905090565b69054b40b1f852bda00000811115610d885760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610dc764e8d4a51000856115b4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610e0d57600080fd5b505af1158015610e21573d6000803e3d6000fd5b50506040516323b872dd60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506323b872dd91506102f2903390309086906004016114d4565b610e7d610d2d565b610e995760405162461bcd60e51b815260040161020a9061152b565b610ec1817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b0316610ee16000805160206116078339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b610f21610d2d565b610f3d5760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac453580546002811415610f815760405162461bcd60e51b815260040161020a9061158c565b60028255610faf610f9e6000805160206116078339815191525490565b6001600160a01b0386169085611160565b50600190555050565b610fc0610d2d565b610fdc5760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535805460028114156110205760405162461bcd60e51b815260040161020a9061158c565b600282557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f51b0fd46040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561107f57600080fd5b505af1158015611093573d6000803e3d6000fd5b50505050600182555050565b6001600160a01b0381166110f55760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015260640161020a565b806001600160a01b03166111156000805160206116078339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36103878160008051602061160783398151915255565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526111b29084906111b7565b505050565b600061120c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112899092919063ffffffff16565b8051909150156111b2578080602001905181019061122a9190611464565b6111b25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161020a565b606061129884846000856112a2565b90505b9392505050565b6060824710156113035760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161020a565b843b6113515760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161020a565b600080866001600160a01b0316858760405161136d91906114b8565b60006040518083038185875af1925050503d80600081146113aa576040519150601f19603f3d011682016040523d82523d6000602084013e6113af565b606091505b50915091506113bf8282866113ca565b979650505050505050565b606083156113d957508161129b565b8251156113e95782518084602001fd5b8160405162461bcd60e51b815260040161020a91906114f8565b80356001600160a01b038116811461141a57600080fd5b919050565b60006020828403121561143157600080fd5b61129b82611403565b6000806040838503121561144d57600080fd5b61145683611403565b946020939093013593505050565b60006020828403121561147657600080fd5b8151801515811461129b57600080fd5b60006020828403121561149857600080fd5b5035919050565b6000602082840312156114b157600080fd5b5051919050565b600082516114ca8184602087016115d6565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208152600082518060208401526115178160408501602087016115d6565b601f01601f19169190910160400192915050565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b60208082526010908201526f416d6f756e7420746f6f206c6172676560801b604082015260600190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b6000826115d157634e487b7160e01b600052601260045260246000fd5b500490565b60005b838110156115f15781810151838201526020016115d9565b83811115611600576000848401525b5050505056fe7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa264697066735822122060627eb094f2c9ae0acd53bfea289004fac1f1e34602265ad04f748612a2d87c64736f6c634300080700337bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063bfc11ffd1161008c578063cb93905311610066578063cb93905314610182578063d38bfff414610195578063f3fef3a3146101a8578063f51b0fd4146101bb57600080fd5b8063bfc11ffd14610144578063c6b6816914610157578063c7af33521461016a57600080fd5b80630c340a24146100d457806335aa0b96146100f95780635981c7461461010e5780635d36b19014610121578063853828b6146101295780638a095a0f14610131575b600080fd5b6100dc6101c3565b6040516001600160a01b0390911681526020015b60405180910390f35b61010c610107366004611486565b6101e0565b005b61010c61011c366004611486565b61038a565b61010c6104eb565b61010c610591565b61010c61013f366004611486565b61098a565b61010c610152366004611486565b610ae6565b61010c610165366004611486565b610c03565b610172610d2d565b60405190151581526020016100f0565b61010c610190366004611486565b610d5e565b61010c6101a336600461141f565b610e75565b61010c6101b636600461143a565b610f19565b61010c610fb8565b60006101db6000805160206116078339815191525490565b905090565b69054b40b1f852bda000008111156102135760405162461bcd60e51b815260040161020a90611562565b60405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd333061025364e8d4a51000866115b4565b6040518463ffffffff1660e01b8152600401610271939291906114d4565b600060405180830381600087803b15801561028b57600080fd5b505af115801561029f573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb91506044015b602060405180830381600087803b15801561030c57600080fd5b505af1158015610320573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103449190611464565b6103875760405162461bcd60e51b815260206004820152601460248201527313d554d1081d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b50565b69054b40b1f852bda000008111156103b45760405162461bcd60e51b815260040161020a90611562565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90610404903390309086906004016114d4565b602060405180830381600087803b15801561041e57600080fd5b505af1158015610432573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104569190611464565b6104985760405162461bcd60e51b8152602060048201526013602482015272111052481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161020a565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016102f2565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b0316146105865760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b606482015260840161020a565b61058f3361109f565b565b610599610d2d565b6105b55760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535805460028114156105f95760405162461bcd60e51b815260040161020a9061158c565b600282556106de6106166000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561067557600080fd5b505afa158015610689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ad919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6107bf6106f76000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561075657600080fd5b505afa15801561076a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078e919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6108a26107d86000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381600087803b15801561083957600080fd5b505af115801561084d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610871919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b6109836108bb6000805160206116078339815191525490565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561091a57600080fd5b505afa15801561092e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610952919061149f565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611160565b5060019055565b69054b40b1f852bda000008111156109b45760405162461bcd60e51b815260040161020a90611562565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90604401602060405180830381600087803b158015610a1c57600080fd5b505af1158015610a30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a549190611464565b610a965760405162461bcd60e51b8152602060048201526013602482015272111052481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161020a565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906102f2903390309086906004016114d4565b69054b40b1f852bda00000811115610b105760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd3330610b5064e8d4a51000866115b4565b6040518463ffffffff1660e01b8152600401610b6e939291906114d4565b602060405180830381600087803b158015610b8857600080fd5b505af1158015610b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc09190611464565b6104985760405162461bcd60e51b81526020600482015260146024820152731554d110c81d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b69054b40b1f852bda00000811115610c2d5760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610c6c64e8d4a51000856115b4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b158015610cb257600080fd5b505af1158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cea9190611464565b610a965760405162461bcd60e51b81526020600482015260146024820152731554d110c81d1c985b9cd9995c8819985a5b195960621b604482015260640161020a565b6000610d456000805160206116078339815191525490565b6001600160a01b0316336001600160a01b031614905090565b69054b40b1f852bda00000811115610d885760405162461bcd60e51b815260040161020a90611562565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610dc764e8d4a51000856115b4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610e0d57600080fd5b505af1158015610e21573d6000803e3d6000fd5b50506040516323b872dd60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506323b872dd91506102f2903390309086906004016114d4565b610e7d610d2d565b610e995760405162461bcd60e51b815260040161020a9061152b565b610ec1817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b0316610ee16000805160206116078339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b610f21610d2d565b610f3d5760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac453580546002811415610f815760405162461bcd60e51b815260040161020a9061158c565b60028255610faf610f9e6000805160206116078339815191525490565b6001600160a01b0386169085611160565b50600190555050565b610fc0610d2d565b610fdc5760405162461bcd60e51b815260040161020a9061152b565b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535805460028114156110205760405162461bcd60e51b815260040161020a9061158c565b600282557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f51b0fd46040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561107f57600080fd5b505af1158015611093573d6000803e3d6000fd5b50505050600182555050565b6001600160a01b0381166110f55760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015260640161020a565b806001600160a01b03166111156000805160206116078339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36103878160008051602061160783398151915255565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526111b29084906111b7565b505050565b600061120c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166112899092919063ffffffff16565b8051909150156111b2578080602001905181019061122a9190611464565b6111b25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161020a565b606061129884846000856112a2565b90505b9392505050565b6060824710156113035760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161020a565b843b6113515760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161020a565b600080866001600160a01b0316858760405161136d91906114b8565b60006040518083038185875af1925050503d80600081146113aa576040519150601f19603f3d011682016040523d82523d6000602084013e6113af565b606091505b50915091506113bf8282866113ca565b979650505050505050565b606083156113d957508161129b565b8251156113e95782518084602001fd5b8160405162461bcd60e51b815260040161020a91906114f8565b80356001600160a01b038116811461141a57600080fd5b919050565b60006020828403121561143157600080fd5b61129b82611403565b6000806040838503121561144d57600080fd5b61145683611403565b946020939093013593505050565b60006020828403121561147657600080fd5b8151801515811461129b57600080fd5b60006020828403121561149857600080fd5b5035919050565b6000602082840312156114b157600080fd5b5051919050565b600082516114ca8184602087016115d6565b9190910192915050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208152600082518060208401526115178160408501602087016115d6565b601f01601f19169190910160400192915050565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b60208082526010908201526f416d6f756e7420746f6f206c6172676560801b604082015260600190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b6000826115d157634e487b7160e01b600052601260045260246000fd5b500490565b60005b838110156115f15781810151838201526020016115d9565b83811115611600576000848401525b5050505056fe7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa264697066735822122060627eb094f2c9ae0acd53bfea289004fac1f1e34602265ad04f748612a2d87c64736f6c63430008070033", "linkReferences": {}, "deployedLinkReferences": {} } From bd17a59b53400417549294d84a00825f709444dc Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Fri, 30 Jun 2023 10:46:10 +0200 Subject: [PATCH 02/67] intermediary commit --- brownie/abi/wsteth.json | 1 + brownie/playingAround.py | 35 +++++++++++++++++++++++++++++------ brownie/world.py | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 brownie/abi/wsteth.json diff --git a/brownie/abi/wsteth.json b/brownie/abi/wsteth.json new file mode 100644 index 0000000000..0550c891ed --- /dev/null +++ b/brownie/abi/wsteth.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"contract IStETH","name":"_stETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wstETHAmount","type":"uint256"}],"name":"getStETHByWstETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmount","type":"uint256"}],"name":"getWstETHByStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stEthPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensPerStEth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wstETHAmount","type":"uint256"}],"name":"unwrap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmount","type":"uint256"}],"name":"wrap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/brownie/playingAround.py b/brownie/playingAround.py index 2392feb8cf..d538537fb0 100644 --- a/brownie/playingAround.py +++ b/brownie/playingAround.py @@ -1,15 +1,38 @@ from world import * +STD = {"from": vault_oeth_admin} # pool factory #https://etherscan.io/address/0xfADa0f4547AB2de89D1304A668C39B3E09Aa7c76#code -pool_id = "0x5aee1e99fe86960377de9f88689616916d5dcabe000000000000000000000467" +# wstETH / WETH +pool_id = "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080" ba_vault=Contract.from_explorer("0xBA12222222228d8Ba445958a75a0704d566BF2C8") ba_batch_relayer = Contract.from_explorer("0xf77018c0d817dA22caDbDf504C00c0d32cE1e5C2") +wstETHPool = Contract.from_explorer("0x32296969ef14eb0c6d29669c550d4a0449130230") -bpt = "0x5aEe1e99fE86960377DE9f88689616916D5DcaBe" -reth.approve(ba_vault, 10**50, {"from": vault_oeth_core}) +#approve steth to wrap into wstETH +steth.approve(wsteth.address, 10**50, STD) +wsteth.wrap(10 * 10**18, STD) -# 1 stands for EXACT_TOKENS_IN_FOR_BPT_OUT -join_request = ([bpt, wsteth, sfrxeth, reth], [0, 0, 0, 10**18], 1 , False) -ba_vault.joinPool(pool_id, vault_oeth_core, vault_oeth_core, join_request, {"from": vault_oeth_core}) +weth.approve(ba_vault, 10**36, STD) +wsteth.approve(ba_vault, 10**36, STD) +ba_vault.joinPool( + pool_id, + vault_oeth_admin.address, #sender + vault_oeth_admin.address, #recipient + [ + [wsteth.address, weth.address], # assets + [10**18, 10**18], # min amounts in + '0x', # userData + False, #fromInternalBalance + ], + STD +) +# bpt = "0x5aEe1e99fE86960377DE9f88689616916D5DcaBe" +# reth.approve(ba_vault, 10**50, {"from": vault_oeth_core}) + +# # 1 stands for EXACT_TOKENS_IN_FOR_BPT_OUT +# join_request = ([bpt, wsteth, sfrxeth, reth], [0, 0, 0, 10**18], 1 , False) +# ba_vault.joinPool(pool_id, vault_oeth_core, vault_oeth_core, join_request, {"from": vault_oeth_core}) + +# # do the same steps as in the SDK and join the pool \ No newline at end of file diff --git a/brownie/world.py b/brownie/world.py index 9f57e65f99..bca0fe0f36 100644 --- a/brownie/world.py +++ b/brownie/world.py @@ -37,7 +37,7 @@ def load_contract(name, address): usdc = load_contract('usdc', USDC) dai = load_contract('dai', DAI) steth = load_contract('ERC20', STETH) -wsteth = load_contract('ERC20', WSTETH) +wsteth = load_contract('wsteth', WSTETH) sfrxeth = load_contract('ERC20', SFRXETH) frxeth = load_contract('ERC20', FRXETH) reth = load_contract('ERC20', RETH) From e218397f56138aea1feb4a584598288d09298e32 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 3 Jul 2023 17:38:24 +0200 Subject: [PATCH 03/67] commit research files --- brownie/abi/balancerUserData.json | 27 +++++++++++++++++++++++++++ brownie/playingAround.py | 26 ++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 brownie/abi/balancerUserData.json diff --git a/brownie/abi/balancerUserData.json b/brownie/abi/balancerUserData.json new file mode 100644 index 0000000000..22844d282c --- /dev/null +++ b/brownie/abi/balancerUserData.json @@ -0,0 +1,27 @@ +[ + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "joinKind", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bptAmountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "enterTokenIndex", + "type": "uint256" + } + ], + "name": "userDataTokenInExactBPTOut", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/brownie/playingAround.py b/brownie/playingAround.py index d538537fb0..e33f01cca1 100644 --- a/brownie/playingAround.py +++ b/brownie/playingAround.py @@ -9,6 +9,8 @@ ba_vault=Contract.from_explorer("0xBA12222222228d8Ba445958a75a0704d566BF2C8") ba_batch_relayer = Contract.from_explorer("0xf77018c0d817dA22caDbDf504C00c0d32cE1e5C2") wstETHPool = Contract.from_explorer("0x32296969ef14eb0c6d29669c550d4a0449130230") +#used just to encode user data. Address is not important since it will never be called +balancerUserDataEncoder = load_contract('balancerUserData', vault_oeth_admin.address) #approve steth to wrap into wstETH steth.approve(wsteth.address, 10**50, STD) @@ -16,18 +18,38 @@ weth.approve(ba_vault, 10**36, STD) wsteth.approve(ba_vault, 10**36, STD) + ba_vault.joinPool( pool_id, vault_oeth_admin.address, #sender vault_oeth_admin.address, #recipient [ - [wsteth.address, weth.address], # assets - [10**18, 10**18], # min amounts in + [weth.address], # assets + [10**18], # min amounts in '0x', # userData False, #fromInternalBalance ], STD ) + +userData = balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(2, 5*10**18, 1) + +0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080 +0x39254033945AA2E4809Cc2977E7087BEE48bd7Ab +0x39254033945AA2E4809Cc2977E7087BEE48bd7Ab +{"assets": ["0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], "maxAmountsIn": ["10000000000000000000", "10000000000000000000"], "userData": "0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000001", "fromInternalBalance": false} + + + +export enum WeightedPoolJoinKind { + INIT = 0, + EXACT_TOKENS_IN_FOR_BPT_OUT, + TOKEN_IN_FOR_EXACT_BPT_OUT, + ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, + ADD_TOKEN, +} + + # bpt = "0x5aEe1e99fE86960377DE9f88689616916D5DcaBe" # reth.approve(ba_vault, 10**50, {"from": vault_oeth_core}) From e40539a29484e85abaa4b737fcf59a60ce78475b Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Tue, 4 Jul 2023 14:32:02 +0200 Subject: [PATCH 04/67] balancer booster abi --- brownie/abi/balancer_booster.json | 1 + brownie/playingAround.py | 61 ++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 brownie/abi/balancer_booster.json diff --git a/brownie/abi/balancer_booster.json b/brownie/abi/balancer_booster.json new file mode 100644 index 0000000000..ccdbf5a0ac --- /dev/null +++ b/brownie/abi/balancer_booster.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"address","name":"_minter","type":"address"},{"internalType":"address","name":"_crv","type":"address"},{"internalType":"address","name":"_voteOwnership","type":"address"},{"internalType":"address","name":"_voteParameter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newArbitrator","type":"address"}],"name":"ArbitratorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"poolid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rewardFactory","type":"address"},{"indexed":false,"internalType":"address","name":"stashFactory","type":"address"},{"indexed":false,"internalType":"address","name":"tokenFactory","type":"address"}],"name":"FactoriesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeDistro","type":"address"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"FeeInfoChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeDistro","type":"address"},{"indexed":false,"internalType":"address","name":"lockFees","type":"address"},{"indexed":false,"internalType":"address","name":"feeToken","type":"address"}],"name":"FeeInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newFeeManager","type":"address"}],"name":"FeeManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lockIncentive","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakerIncentive","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"earmarkIncentive","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"platformFee","type":"uint256"}],"name":"FeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lpToken","type":"address"},{"indexed":false,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"rewardPool","type":"address"},{"indexed":false,"internalType":"address","name":"stash","type":"address"},{"indexed":false,"internalType":"uint256","name":"pid","type":"uint256"}],"name":"PoolAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPoolManager","type":"address"}],"name":"PoolManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"}],"name":"PoolShutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lockRewards","type":"address"},{"indexed":false,"internalType":"address","name":"stakerRewards","type":"address"}],"name":"RewardContractsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasuryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newVoteDelegate","type":"address"}],"name":"VoteDelegateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"poolid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MaxFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_MULTIPLIER_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_lptoken","type":"address"},{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"uint256","name":"_stashVersion","type":"uint256"}],"name":"addPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bridgeDelegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_gauge","type":"address"}],"name":"claimRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"crv","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_stake","type":"bool"}],"name":"deposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"bool","name":"_stake","type":"bool"}],"name":"depositAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"distributeL2Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeToken","type":"address"}],"name":"earmarkFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"earmarkIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"earmarkRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"feeTokens","outputs":[{"internalType":"address","name":"distro","type":"address"},{"internalType":"address","name":"rewards","type":"address"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaugeMap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getRewardMultipliers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"l2FeesHistory","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockRewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"address","name":"lptoken","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"crvRewards","type":"address"},{"internalType":"address","name":"stash","type":"address"},{"internalType":"bool","name":"shutdown","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardArbitrator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"rewardClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_arb","type":"address"}],"name":"setArbitrator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridgeDelegate","type":"address"}],"name":"setBridgeDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegateContract","type":"address"},{"internalType":"address","name":"_delegate","type":"address"},{"internalType":"bytes32","name":"_space","type":"bytes32"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rfactory","type":"address"},{"internalType":"address","name":"_sfactory","type":"address"},{"internalType":"address","name":"_tfactory","type":"address"}],"name":"setFactories","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeToken","type":"address"},{"internalType":"address","name":"_feeDistro","type":"address"}],"name":"setFeeInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeM","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockFees","type":"uint256"},{"internalType":"uint256","name":"_stakerFees","type":"uint256"},{"internalType":"uint256","name":"_callerFees","type":"uint256"},{"internalType":"uint256","name":"_platform","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"setGaugeRedirect","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolM","type":"address"}],"name":"setPoolManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewards","type":"address"},{"internalType":"address","name":"_stakerRewards","type":"address"}],"name":"setRewardContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rewardContract","type":"address"},{"internalType":"uint256","name":"multiplier","type":"uint256"}],"name":"setRewardMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"setVote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_voteDelegate","type":"address"}],"name":"setVoteDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"shutdownPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutdownSystem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"staker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakerIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakerRewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stashFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_feeToken","type":"address"},{"internalType":"bool","name":"_active","type":"bool"}],"name":"updateFeeInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_voteId","type":"uint256"},{"internalType":"address","name":"_votingAddress","type":"address"},{"internalType":"bool","name":"_support","type":"bool"}],"name":"vote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"voteDelegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauge","type":"address[]"},{"internalType":"uint256[]","name":"_weight","type":"uint256[]"}],"name":"voteGaugeWeight","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"voteOwnership","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voteParameter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"withdrawAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawTo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/brownie/playingAround.py b/brownie/playingAround.py index e33f01cca1..d8aaa4e781 100644 --- a/brownie/playingAround.py +++ b/brownie/playingAround.py @@ -1,9 +1,14 @@ from world import * +#STD = {"from": vault_oeth_admin, "gas_price": 100} STD = {"from": vault_oeth_admin} # pool factory #https://etherscan.io/address/0xfADa0f4547AB2de89D1304A668C39B3E09Aa7c76#code +#eth_whale = "0x00000000219ab540356cbb839cbe05303d7705fa" +#whale = accounts.at(eth_whale, force=True) + + # wstETH / WETH pool_id = "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080" ba_vault=Contract.from_explorer("0xBA12222222228d8Ba445958a75a0704d566BF2C8") @@ -11,6 +16,11 @@ wstETHPool = Contract.from_explorer("0x32296969ef14eb0c6d29669c550d4a0449130230") #used just to encode user data. Address is not important since it will never be called balancerUserDataEncoder = load_contract('balancerUserData', vault_oeth_admin.address) +# get it via coordinator: https://etherscan.io/address/0xaA54f3b282805822419265208e669d12372a3811 +booster = load_contract('balancer_booster', "0xA57b8d98dAE62B26Ec3bcC4a365338157060B234") + +#rewards contract & depositor +rewardPool = Contract.from_explorer("0x59d66c58e83a26d6a0e35114323f65c3945c89c1") #approve steth to wrap into wstETH steth.approve(wsteth.address, 10**50, STD) @@ -19,19 +29,50 @@ weth.approve(ba_vault, 10**36, STD) wsteth.approve(ba_vault, 10**36, STD) +# Enter the pool ba_vault.joinPool( pool_id, vault_oeth_admin.address, #sender vault_oeth_admin.address, #recipient [ - [weth.address], # assets - [10**18], # min amounts in - '0x', # userData + # tokens need to be sorted numerically + [wsteth.address, weth.address], # assets + # indexes match above assets + [10*10**18, 10*10**18], # min amounts in + # userData = balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(2, 5*10**18, 1) + '0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000001', # userData False, #fromInternalBalance ], STD ) +bpt_balance = wstETHPool.balanceOf(vault_oeth_admin) + +# Exit the pool +ba_vault.exitPool( + pool_id, + vault_oeth_admin.address, #sender + vault_oeth_admin.address, #recipient + [ + # tokens need to be sorted numerically + # we should account for some slippage here since it comes down to balance amounts in the pool + [wsteth.address, weth.address], # assets + [1*10**18, 0], # min amounts out + # userData = balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(0, bpt_balance, 0) + '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000000000000000000', # userData + False, #fromInternalBalance + ], + STD +) + +wstETHPool.approve(rewardPool, 1e50, STD) +# DEPLOY TO AURA +rewardPool.deposit(bpt_balance, oeth_vault_admin, STD) +# WITHDRAW FROM AURA +rewardPool.withdraw(10000000000000000000, oeth_vault_admin, oeth_vault_admin, STD) + + + userData = balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(2, 5*10**18, 1) 0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080 @@ -43,12 +84,20 @@ export enum WeightedPoolJoinKind { INIT = 0, - EXACT_TOKENS_IN_FOR_BPT_OUT, - TOKEN_IN_FOR_EXACT_BPT_OUT, - ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, + EXACT_TOKENS_IN_FOR_BPT_OUT, #User sends precise quantities of tokens, and receives an estimated but unknown (computed at run time) quantity of BPT. + TOKEN_IN_FOR_EXACT_BPT_OUT, #User sends an estimated but unknown (computed at run time) quantity of a single token, and receives a precise quantity of BPT. + ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, # User sends estimated but unknown (computed at run time) quantities of tokens, and receives precise quantity of BPT ADD_TOKEN, } +export enum ExitKind { + EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, #([EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, bptAmountIn, exitTokenIndex]) User sends a precise quantity of BPT, and receives an estimated but unknown (computed at run time) quantity of a single token + EXACT_BPT_IN_FOR_TOKENS_OUT, #User sends a precise quantity of BPT, and receives an estimated but unknown (computed at run time) quantities of all tokens + BPT_IN_FOR_EXACT_TOKENS_OUT, # User sends an estimated but unknown (computed at run time) quantity of BPT, and receives precise quantities of specified tokens + MANAGEMENT_FEE_TOKENS_OUT // for InvestmentPool +} + + # bpt = "0x5aEe1e99fE86960377DE9f88689616916D5DcaBe" # reth.approve(ba_vault, 10**50, {"from": vault_oeth_core}) From fddfc96b7591c0cccfe4a22db4f462d0693802e6 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 5 Jul 2023 22:13:20 +0200 Subject: [PATCH 05/67] intermittent commit --- brownie/playingAround.py | 51 ++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/brownie/playingAround.py b/brownie/playingAround.py index d8aaa4e781..ccb7b9893e 100644 --- a/brownie/playingAround.py +++ b/brownie/playingAround.py @@ -9,6 +9,21 @@ #whale = accounts.at(eth_whale, force=True) +# export enum WeightedPoolJoinKind { +# INIT = 0, +# EXACT_TOKENS_IN_FOR_BPT_OUT, #User sends precise quantities of tokens, and receives an estimated but unknown (computed at run time) quantity of BPT. +# TOKEN_IN_FOR_EXACT_BPT_OUT, #User sends an estimated but unknown (computed at run time) quantity of a single token, and receives a precise quantity of BPT. +# ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, # User sends estimated but unknown (computed at run time) quantities of tokens, and receives precise quantity of BPT +# ADD_TOKEN, +# } + +# export enum ExitKind { +# EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, #([EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, bptAmountIn, exitTokenIndex]) User sends a precise quantity of BPT, and receives an estimated but unknown (computed at run time) quantity of a single token +# EXACT_BPT_IN_FOR_TOKENS_OUT, #User sends a precise quantity of BPT, and receives an estimated but unknown (computed at run time) quantities of all tokens +# BPT_IN_FOR_EXACT_TOKENS_OUT, # User sends an estimated but unknown (computed at run time) quantity of BPT, and receives precise quantities of specified tokens +# MANAGEMENT_FEE_TOKENS_OUT // for InvestmentPool +# } + # wstETH / WETH pool_id = "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080" ba_vault=Contract.from_explorer("0xBA12222222228d8Ba445958a75a0704d566BF2C8") @@ -19,6 +34,8 @@ # get it via coordinator: https://etherscan.io/address/0xaA54f3b282805822419265208e669d12372a3811 booster = load_contract('balancer_booster', "0xA57b8d98dAE62B26Ec3bcC4a365338157060B234") +# DEPOSIT INTO META STABLE POOL + #rewards contract & depositor rewardPool = Contract.from_explorer("0x59d66c58e83a26d6a0e35114323f65c3945c89c1") @@ -70,40 +87,12 @@ rewardPool.deposit(bpt_balance, oeth_vault_admin, STD) # WITHDRAW FROM AURA rewardPool.withdraw(10000000000000000000, oeth_vault_admin, oeth_vault_admin, STD) +# END OF DEPOSIT INTO META STABLE POOL -userData = balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(2, 5*10**18, 1) - -0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080 -0x39254033945AA2E4809Cc2977E7087BEE48bd7Ab -0x39254033945AA2E4809Cc2977E7087BEE48bd7Ab -{"assets": ["0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], "maxAmountsIn": ["10000000000000000000", "10000000000000000000"], "userData": "0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000001", "fromInternalBalance": false} - - - -export enum WeightedPoolJoinKind { - INIT = 0, - EXACT_TOKENS_IN_FOR_BPT_OUT, #User sends precise quantities of tokens, and receives an estimated but unknown (computed at run time) quantity of BPT. - TOKEN_IN_FOR_EXACT_BPT_OUT, #User sends an estimated but unknown (computed at run time) quantity of a single token, and receives a precise quantity of BPT. - ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, # User sends estimated but unknown (computed at run time) quantities of tokens, and receives precise quantity of BPT - ADD_TOKEN, -} - -export enum ExitKind { - EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, #([EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, bptAmountIn, exitTokenIndex]) User sends a precise quantity of BPT, and receives an estimated but unknown (computed at run time) quantity of a single token - EXACT_BPT_IN_FOR_TOKENS_OUT, #User sends a precise quantity of BPT, and receives an estimated but unknown (computed at run time) quantities of all tokens - BPT_IN_FOR_EXACT_TOKENS_OUT, # User sends an estimated but unknown (computed at run time) quantity of BPT, and receives precise quantities of specified tokens - MANAGEMENT_FEE_TOKENS_OUT // for InvestmentPool -} - - +# DEPOSIT INTO COMPOSABLE POOL -# bpt = "0x5aEe1e99fE86960377DE9f88689616916D5DcaBe" -# reth.approve(ba_vault, 10**50, {"from": vault_oeth_core}) -# # 1 stands for EXACT_TOKENS_IN_FOR_BPT_OUT -# join_request = ([bpt, wsteth, sfrxeth, reth], [0, 0, 0, 10**18], 1 , False) -# ba_vault.joinPool(pool_id, vault_oeth_core, vault_oeth_core, join_request, {"from": vault_oeth_core}) -# # do the same steps as in the SDK and join the pool \ No newline at end of file +# END DEPOSIT INTO COMPOSABLE POOL From 4d61080027f47210fd0ee73643010a8ef5093b89 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Tue, 11 Jul 2023 11:52:19 +0200 Subject: [PATCH 06/67] add base balancer contract that implements checkBalance functionality --- .../contracts/interfaces/IBalancerVault.sol | 128 ++++++++++++++++ .../strategies/BaseBalancerStrategy.sol | 141 ++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 contracts/contracts/interfaces/IBalancerVault.sol create mode 100644 contracts/contracts/strategies/BaseBalancerStrategy.sol diff --git a/contracts/contracts/interfaces/IBalancerVault.sol b/contracts/contracts/interfaces/IBalancerVault.sol new file mode 100644 index 0000000000..11f8e828f6 --- /dev/null +++ b/contracts/contracts/interfaces/IBalancerVault.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IERC20 } from "../utils/InitializableAbstractStrategy.sol"; + +interface IAsset { + // solhint-disable-previous-line no-empty-blocks +} + +interface IBalancerVault { + /** + * @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will + * trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized + * Pool shares. + * + * If the caller is not `sender`, it must be an authorized relayer for them. + * + * The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount + * to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces + * these maximums. + * + * If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable + * this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the + * WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent + * back to the caller (not the sender, which is important for relayers). + * + * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when + * interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be + * sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final + * `assets` array might not be sorted. Pools with no registered tokens cannot be joined. + * + * If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only + * be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be + * withdrawn from Internal Balance: attempting to do so will trigger a revert. + * + * This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement + * their own custom logic. This typically requires additional information from the user (such as the expected number + * of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed + * directly to the Pool's contract, as is `recipient`. + * + * Emits a `PoolBalanceChanged` event. + */ + function joinPool( + bytes32 poolId, + address sender, + address recipient, + JoinPoolRequest memory request + ) external payable; + + struct JoinPoolRequest { + IAsset[] assets; + uint256[] maxAmountsIn; + bytes userData; + bool fromInternalBalance; + } + + /** + * @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will + * trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized + * Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see + * `getPoolTokenInfo`). + * + * If the caller is not `sender`, it must be an authorized relayer for them. + * + * The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum + * token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault: + * it just enforces these minimums. + * + * If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To + * enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead + * of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit. + * + * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when + * interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must + * be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the + * final `assets` array might not be sorted. Pools with no registered tokens cannot be exited. + * + * If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise, + * an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to + * do so will trigger a revert. + * + * `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the + * `tokens` array. This array must match the Pool's registered tokens. + * + * This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement + * their own custom logic. This typically requires additional information from the user (such as the expected number + * of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and + * passed directly to the Pool's contract. + * + * Emits a `PoolBalanceChanged` event. + */ + function exitPool( + bytes32 poolId, + address sender, + address payable recipient, + ExitPoolRequest memory request + ) external; + + struct ExitPoolRequest { + IAsset[] assets; + uint256[] minAmountsOut; + bytes userData; + bool toInternalBalance; + } + + /** + * @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of + * the tokens' `balances` changed. + * + * The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all + * Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order. + * + * If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same + * order as passed to `registerTokens`. + * + * Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are + * the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo` + * instead. + */ + function getPoolTokens(bytes32 poolId) + external + view + returns ( + IERC20[] memory tokens, + uint256[] memory balances, + uint256 lastChangeBlock + ); +} diff --git a/contracts/contracts/strategies/BaseBalancerStrategy.sol b/contracts/contracts/strategies/BaseBalancerStrategy.sol new file mode 100644 index 0000000000..382b3c9e29 --- /dev/null +++ b/contracts/contracts/strategies/BaseBalancerStrategy.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title OETH Base Balancer Abstract Strategy + * @author Origin Protocol Inc + */ +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { IERC20, InitializableAbstractStrategy } from "../utils/InitializableAbstractStrategy.sol"; +import { IBalancerVault } from "../interfaces/IBalancerVault.sol"; + +abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { + using SafeERC20 for IERC20; + address internal auraDepositorAddress; + address internal auraRewardStakerAddress; + uint256 internal auraDepositorPTokenId; + address internal pTokenAddress; + bytes32 internal balancerPoolId; + // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) + uint256 public maxWithdrawalSlippage; + int256[50] private __reserved; + IBalancerVault private balancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); + + event MaxWithdrawalSlippageUpdated( + uint256 _prevMaxSlippagePercentage, + uint256 _newMaxSlippagePercentage + ); + + /** + * Initializer for setting up strategy internal state. This overrides the + * InitializableAbstractStrategy initializer as Balancer's strategies don't fit + * well within that abstraction. + * @param _rewardTokenAddresses Address of BAL & AURA + * @param _assets Addresses of supported assets. MUST be passed in the same + * order as returned by coins on the pool contract, i.e. + * WETH, stETH + * @param _pTokens Platform Token corresponding addresses + * @param platformAddress Address of the Balancer's 3pool + * @param vaultAddress Address of the vault + * @param auraDepositorAddress Address of the Auraa depositor(AKA booster) for this pool + * @param auraRewardStakerAddress Address of the Aura rewards staker + * @param auraDepositorPTokenId Address of the Aura rewards staker + */ + function initialize( + address[] calldata _rewardTokenAddresses, // BAL & AURA + address[] calldata _assets, + address[] calldata _pTokens, + address platformAddress, + address vaultAddress, + address auraDepositorAddress, + address auraRewardStakerAddress, + uint256 auraDepositorPTokenId, + bytes32 balancerPoolId + ) external onlyGovernor initializer { + auraDepositorAddress = auraDepositorAddress; + auraRewardStakerAddress = auraRewardStakerAddress; + auraDepositorPTokenId = auraDepositorPTokenId; + pTokenAddress = _pTokens[0]; + maxWithdrawalSlippage = 1e15; + balancerPoolId = balancerPoolId; + + super._initialize( + platformAddress, + vaultAddress, + _rewardTokenAddresses, + _assets, + _pTokens + ); + _approveBase(); + } + + /** + * @dev Returns bool indicating whether asset is supported by strategy + * @param _asset Address of the asset + */ + function supportsAsset(address _asset) + external + view + override + returns (bool) + { + return assetToPToken[_asset] != address(0); + } + + function checkBalance(address _asset) + external + view + override + returns (uint256) + { + (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock) = balancerVault.getPoolTokens(balancerPoolId); + // TODO: override in AURA implementation + uint256 yourPoolShare = IERC20(pTokenAddress).balanceOf(address(this)) / IERC20(pTokenAddress).totalSupply(); + + uint256 balancesLength = balances.length; + for (uint256 i=0; i < balances.length; ++i){ + if(address(tokens[i]) == _asset) { + return balances[i] * yourPoolShare; + } + } + } + + + + /** + * @dev Sets max withdrawal slippage that is considered when removing + * liquidity from Balancer pools. + * @param _maxWithdrawalSlippage Max withdrawal slippage denominated in + * wad (number with 18 decimals): 1e18 == 100%, 1e16 == 1% + * + * IMPORTANT Minimum maxWithdrawalSlippage should actually be 0.1% (1e15) + * for production usage. Contract allows as low value as 0% for confirming + * correct behavior in test suite. + */ + function setMaxWithdrawalSlippage(uint256 _maxWithdrawalSlippage) + external + onlyVaultOrGovernorOrStrategist + { + require( + _maxWithdrawalSlippage <= 1e18, + "Max withdrawal slippage needs to be between 0% - 100%" + ); + emit MaxWithdrawalSlippageUpdated( + maxWithdrawalSlippage, + _maxWithdrawalSlippage + ); + maxWithdrawalSlippage = _maxWithdrawalSlippage; + } + + function _approveBase() internal { + IERC20 pToken = IERC20(pTokenAddress); + // Balancer vault for BPT token (required for removing liquidity) + pToken.safeApprove(address(balancerVault), 0); + pToken.safeApprove(address(balancerVault), type(uint256).max); + + // Gauge for LP token + pToken.safeApprove(auraDepositorAddress, 0); + pToken.safeApprove(auraDepositorAddress, type(uint256).max); + } + +} \ No newline at end of file From c941766a41000a730501315912d1dc64c37bce8b Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 12 Jul 2023 15:54:02 +0200 Subject: [PATCH 07/67] add some additional initial integration --- .../{ => balancer}/IBalancerVault.sol | 2 +- .../interfaces/balancer/IMetaStablePool.sol | 8 ++ .../interfaces/balancer/IRateProvider.sol | 20 +++++ .../balancer/BalancerMetaPoolStrategy.sol | 71 +++++++++++++++++ .../{ => balancer}/BaseBalancerStrategy.sol | 79 ++++++++++++++----- 5 files changed, 159 insertions(+), 21 deletions(-) rename contracts/contracts/interfaces/{ => balancer}/IBalancerVault.sol (98%) create mode 100644 contracts/contracts/interfaces/balancer/IMetaStablePool.sol create mode 100644 contracts/contracts/interfaces/balancer/IRateProvider.sol create mode 100644 contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol rename contracts/contracts/strategies/{ => balancer}/BaseBalancerStrategy.sol (61%) diff --git a/contracts/contracts/interfaces/IBalancerVault.sol b/contracts/contracts/interfaces/balancer/IBalancerVault.sol similarity index 98% rename from contracts/contracts/interfaces/IBalancerVault.sol rename to contracts/contracts/interfaces/balancer/IBalancerVault.sol index 11f8e828f6..47773769d6 100644 --- a/contracts/contracts/interfaces/IBalancerVault.sol +++ b/contracts/contracts/interfaces/balancer/IBalancerVault.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IERC20 } from "../utils/InitializableAbstractStrategy.sol"; +import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; interface IAsset { // solhint-disable-previous-line no-empty-blocks diff --git a/contracts/contracts/interfaces/balancer/IMetaStablePool.sol b/contracts/contracts/interfaces/balancer/IMetaStablePool.sol new file mode 100644 index 0000000000..74d622a65a --- /dev/null +++ b/contracts/contracts/interfaces/balancer/IMetaStablePool.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IRateProvider } from "./IRateProvider.sol"; + +interface IMetaStablePool { + function getRateProviders() external view returns (IRateProvider[] memory providers); +} \ No newline at end of file diff --git a/contracts/contracts/interfaces/balancer/IRateProvider.sol b/contracts/contracts/interfaces/balancer/IRateProvider.sol new file mode 100644 index 0000000000..21c461e7ab --- /dev/null +++ b/contracts/contracts/interfaces/balancer/IRateProvider.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pragma solidity ^0.8.0; + +// TODO: pull this from the monorepo +interface IRateProvider { + function getRate() external view returns (uint256); +} \ No newline at end of file diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol new file mode 100644 index 0000000000..a3dd093888 --- /dev/null +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -0,0 +1,71 @@ +pragma solidity ^0.8.0; + +/** + * @title OETH Balancer MetaStablePool Strategy + * @author Origin Protocol Inc + */ +import { BaseBalancerStrategy } from "./BaseBalancerStrategy.sol"; +import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; +import { IMetaStablePool } from "../../interfaces/balancer/IMetaStablePool.sol"; + +contract BalancerMetaPoolStrategy is BaseBalancerStrategy { + + function getRateProviderRate(address _asset) + internal + override + view + returns(uint256) + { + IMetaStablePool pool = IMetaStablePool(platformAddress); + IRateProvider[] memory providers = pool.getRateProviders(); + + uint256 providersLength = providers.length; + for (uint256 i = 0; i < providersLength; ++i) { + // _assets and corresponding rate providers are all in the same order + if (assetsMapped[i] == _asset) { + return providers[i].getRate(); + } + } + + // should never happen + require(false, "Can not find rateProvider"); + } + + function withdraw( + address _recipient, + address _weth, + uint256 _amount + ) external override onlyVault nonReentrant + { + + } + + function withdrawAll() external override onlyVaultOrGovernor nonReentrant { + + } + + function deposit(address _weth, uint256 _amount) + external + override + onlyVault + nonReentrant + { + } + + function depositAll() external override onlyVault nonReentrant { + } + + function safeApproveAllTokens() + external + override + onlyGovernor + nonReentrant + { + } + + function _abstractSetPToken(address _asset, address _pToken) + internal + override + {} + +} \ No newline at end of file diff --git a/contracts/contracts/strategies/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol similarity index 61% rename from contracts/contracts/strategies/BaseBalancerStrategy.sol rename to contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 382b3c9e29..7dcf64f661 100644 --- a/contracts/contracts/strategies/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -6,8 +6,11 @@ pragma solidity ^0.8.0; * @author Origin Protocol Inc */ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { IERC20, InitializableAbstractStrategy } from "../utils/InitializableAbstractStrategy.sol"; -import { IBalancerVault } from "../interfaces/IBalancerVault.sol"; +import { IERC20, InitializableAbstractStrategy } from "../../utils/InitializableAbstractStrategy.sol"; +import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; +import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; +import { IOracle } from "../../interfaces/IOracle.sol"; +import { IVault } from "../../interfaces/IVault.sol"; abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { using SafeERC20 for IERC20; @@ -26,6 +29,15 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256 _newMaxSlippagePercentage ); + struct InitConfig { + address platformAddress; // platformAddress Address of the Balancer's pool + address vaultAddress; // vaultAddress Address of the vault + address auraDepositorAddress; // auraDepositorAddress Address of the Auraa depositor(AKA booster) for this pool + address auraRewardStakerAddress; // auraRewardStakerAddress Address of the Aura rewards staker + uint256 auraDepositorPTokenId; // auraDepositorPTokenId Address of the Aura rewards staker + bytes32 balancerPoolId; // balancerPoolId bytes32 poolId + } + /** * Initializer for setting up strategy internal state. This overrides the * InitializableAbstractStrategy initializer as Balancer's strategies don't fit @@ -35,33 +47,31 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * order as returned by coins on the pool contract, i.e. * WETH, stETH * @param _pTokens Platform Token corresponding addresses - * @param platformAddress Address of the Balancer's 3pool - * @param vaultAddress Address of the vault - * @param auraDepositorAddress Address of the Auraa depositor(AKA booster) for this pool - * @param auraRewardStakerAddress Address of the Aura rewards staker - * @param auraDepositorPTokenId Address of the Aura rewards staker + * @param initConfig additional configuration */ function initialize( address[] calldata _rewardTokenAddresses, // BAL & AURA address[] calldata _assets, address[] calldata _pTokens, - address platformAddress, - address vaultAddress, - address auraDepositorAddress, - address auraRewardStakerAddress, - uint256 auraDepositorPTokenId, - bytes32 balancerPoolId + InitConfig calldata initConfig ) external onlyGovernor initializer { - auraDepositorAddress = auraDepositorAddress; - auraRewardStakerAddress = auraRewardStakerAddress; - auraDepositorPTokenId = auraDepositorPTokenId; + auraDepositorAddress = initConfig.auraDepositorAddress; + auraRewardStakerAddress = initConfig.auraRewardStakerAddress; + auraDepositorPTokenId = initConfig.auraDepositorPTokenId; pTokenAddress = _pTokens[0]; maxWithdrawalSlippage = 1e15; - balancerPoolId = balancerPoolId; + balancerPoolId = initConfig.balancerPoolId; + + IERC20[] memory poolAssets = getPoolAssets(); + uint256 assetsLength = _assets.length; + require (poolAssets.length == assetsLength, "Pool assets and _assets should be the same length."); + for (uint256 i = 0; i < assetsLength; ++i) { + require(_assets[i] == address(poolAssets[i]), "Pool assets and _assets should all have the same numerical order."); + } super._initialize( - platformAddress, - vaultAddress, + initConfig.platformAddress, + initConfig.vaultAddress, _rewardTokenAddresses, _assets, _pTokens @@ -100,7 +110,36 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } } - + + + function getMinBPTExpected(address _asset, uint256 _amount) + internal + view + virtual + returns (uint256 minBptAmount) + { + address priceProvider = IVault(vaultAddress).priceProvider(); + uint256 marketPrice = IOracle(priceProvider).price(_asset); + uint256 rateProviderRate = getRateProviderRate(_asset); + + // TODO: account for some slippage? + return marketPrice / rateProviderRate; + } + + function getRateProviderRate(address _asset) internal virtual view returns(uint256); + + /** + * Balancer returns assets and rateProviders for corresponding assets ordered + * by numerical order. + */ + function getPoolAssets() + internal + view + returns(IERC20[] memory assets) + { + (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock) = balancerVault.getPoolTokens(balancerPoolId); + return tokens; + } /** * @dev Sets max withdrawal slippage that is considered when removing From a163e8f589e22adcc785f3a5ad2bc6fb046fac43 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Fri, 14 Jul 2023 14:00:26 +0200 Subject: [PATCH 08/67] intermittent commit --- contracts/contracts/interfaces/IWstETH.sol | 29 ++++ .../interfaces/balancer/IBalancerVault.sol | 23 ++- contracts/contracts/proxies/Proxies.sol | 7 + .../balancer/BalancerMetaPoolStrategy.sol | 49 +++++- .../balancer/BaseBalancerStrategy.sol | 66 +++++++- contracts/deploy/043_convexOUSDMeta.js | 2 +- contracts/deploy/071_balancer_wstETH_WETH.js | 145 ++++++++++++++++++ contracts/utils/addresses.js | 5 + contracts/utils/constants.js | 2 + 9 files changed, 317 insertions(+), 11 deletions(-) create mode 100644 contracts/contracts/interfaces/IWstETH.sol create mode 100644 contracts/deploy/071_balancer_wstETH_WETH.js diff --git a/contracts/contracts/interfaces/IWstETH.sol b/contracts/contracts/interfaces/IWstETH.sol new file mode 100644 index 0000000000..b35d04df24 --- /dev/null +++ b/contracts/contracts/interfaces/IWstETH.sol @@ -0,0 +1,29 @@ +pragma solidity ^0.8.0; + +interface IWstETH { + /** + * @notice Get amount of wstETH for a given amount of stETH + * @param _stETHAmount amount of stETH + * @return Amount of wstETH for a given stETH amount + */ + function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256); + + /** + * @notice Get amount of stETH for a given amount of wstETH + * @param _wstETHAmount amount of wstETH + * @return Amount of stETH for a given wstETH amount + */ + function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256); + + /** + * @notice Get amount of stETH for a one wstETH + * @return Amount of stETH for 1 wstETH + */ + function stEthPerToken() external view returns (uint256); + + /** + * @notice Get amount of wstETH for a one stETH + * @return Amount of wstETH for a 1 stETH + */ + function tokensPerStEth() external view returns (uint256); +} \ No newline at end of file diff --git a/contracts/contracts/interfaces/balancer/IBalancerVault.sol b/contracts/contracts/interfaces/balancer/IBalancerVault.sol index 47773769d6..304b36d5c4 100644 --- a/contracts/contracts/interfaces/balancer/IBalancerVault.sol +++ b/contracts/contracts/interfaces/balancer/IBalancerVault.sol @@ -3,11 +3,22 @@ pragma solidity ^0.8.0; import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; -interface IAsset { - // solhint-disable-previous-line no-empty-blocks -} - interface IBalancerVault { + enum WeightedPoolJoinKind { + INIT, + EXACT_TOKENS_IN_FOR_BPT_OUT, + TOKEN_IN_FOR_EXACT_BPT_OUT, + ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, + ADD_TOKEN + } + + enum WeightedPoolExitKind { + EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, + EXACT_BPT_IN_FOR_TOKENS_OUT, + BPT_IN_FOR_EXACT_TOKENS_OUT, + REMOVE_TOKEN + } + /** * @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will * trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized @@ -48,7 +59,7 @@ interface IBalancerVault { ) external payable; struct JoinPoolRequest { - IAsset[] assets; + address[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; @@ -97,7 +108,7 @@ interface IBalancerVault { ) external; struct ExitPoolRequest { - IAsset[] assets; + address[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; diff --git a/contracts/contracts/proxies/Proxies.sol b/contracts/contracts/proxies/Proxies.sol index e7ac9fe1b4..9888b2ec22 100644 --- a/contracts/contracts/proxies/Proxies.sol +++ b/contracts/contracts/proxies/Proxies.sol @@ -156,3 +156,10 @@ contract BuybackProxy is InitializeGovernedUpgradeabilityProxy { contract OETHMorphoAaveStrategyProxy is InitializeGovernedUpgradeabilityProxy { } + +/** + * @notice OETHBalancerMetaPoolStrategyProxy delegates calls to a BalancerMetaPoolStrategy implementation + */ +contract OETHBalancerMetaPoolStrategyProxy is InitializeGovernedUpgradeabilityProxy { + +} diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index a3dd093888..648b57bbea 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -5,8 +5,10 @@ pragma solidity ^0.8.0; * @author Origin Protocol Inc */ import { BaseBalancerStrategy } from "./BaseBalancerStrategy.sol"; +import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { IMetaStablePool } from "../../interfaces/balancer/IMetaStablePool.sol"; +import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; contract BalancerMetaPoolStrategy is BaseBalancerStrategy { @@ -33,7 +35,7 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { function withdraw( address _recipient, - address _weth, + address _asset, uint256 _amount ) external override onlyVault nonReentrant { @@ -44,15 +46,58 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { } - function deposit(address _weth, uint256 _amount) + function deposit(address _asset, uint256 _amount) external override onlyVault nonReentrant { + _deposit(_asset, _amount); } function depositAll() external override onlyVault nonReentrant { + uint256 assetsLength = assetsMapped.length; + for (uint256 i = 0; i < assetsLength; ++i) { + uint256 balance = IERC20(assetsMapped[i]).balanceOf(address(this)); + if (balance > 0) { + _deposit(assetsMapped[i], balance); + } + } + } + + function _deposit(address _asset, uint256 _amount) + internal + { + (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); + + (IERC20[] memory tokens,,) = balancerVault.getPoolTokens(balancerPoolId); + uint256 tokensLength = tokens.length; + uint256[] memory maxAmountsIn = new uint256[](tokensLength); + uint256 assetIndex = 0; + address[] memory joinPoolAssets = new address[](tokensLength); + for (uint256 i = 0; i < tokensLength; ++i) { + joinPoolAssets[i] = address(tokens[i]); + if (address(tokens[i]) == poolAsset) { + maxAmountsIn[i] = poolAmount; + assetIndex = i; + } else { + maxAmountsIn[i] = 0; + } + } + + /* TOKEN_IN_FOR_EXACT_BPT_OUT: + * User sends an estimated but unknown (computed at run time) quantity of a single token, + * and receives a precise quantity of BPT. + * + * ['uint256', 'uint256', 'uint256'] + * [TOKEN_IN_FOR_EXACT_BPT_OUT, bptAmountOut, enterTokenIndex] + */ + bytes memory userData = abi.encode(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, getMinBPTExpected(poolAsset, poolAmount), assetIndex); + + IBalancerVault.JoinPoolRequest memory request = IBalancerVault.JoinPoolRequest(joinPoolAssets, maxAmountsIn, userData, false); + balancerVault.joinPool(balancerPoolId, address(this), address(this), request); + + _lpDepositAll(); } function safeApproveAllTokens() diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 7dcf64f661..0cd97538a7 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -11,6 +11,9 @@ import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { IOracle } from "../../interfaces/IOracle.sol"; import { IVault } from "../../interfaces/IVault.sol"; +import { IWstETH } from "../../interfaces/IWstETH.sol"; +import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; +import "hardhat/console.sol"; abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { using SafeERC20 for IERC20; @@ -19,10 +22,10 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256 internal auraDepositorPTokenId; address internal pTokenAddress; bytes32 internal balancerPoolId; + IBalancerVault internal balancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) uint256 public maxWithdrawalSlippage; int256[50] private __reserved; - IBalancerVault private balancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); event MaxWithdrawalSlippageUpdated( uint256 _prevMaxSlippagePercentage, @@ -55,13 +58,14 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { address[] calldata _pTokens, InitConfig calldata initConfig ) external onlyGovernor initializer { + console.log("sol 1"); auraDepositorAddress = initConfig.auraDepositorAddress; auraRewardStakerAddress = initConfig.auraRewardStakerAddress; auraDepositorPTokenId = initConfig.auraDepositorPTokenId; pTokenAddress = _pTokens[0]; maxWithdrawalSlippage = 1e15; balancerPoolId = initConfig.balancerPoolId; - + console.log("sol 2"); IERC20[] memory poolAssets = getPoolAssets(); uint256 assetsLength = _assets.length; require (poolAssets.length == assetsLength, "Pool assets and _assets should be the same length."); @@ -69,6 +73,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { require(_assets[i] == address(poolAssets[i]), "Pool assets and _assets should all have the same numerical order."); } + console.log("sol 3"); super._initialize( initConfig.platformAddress, initConfig.vaultAddress, @@ -128,6 +133,16 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { function getRateProviderRate(address _asset) internal virtual view returns(uint256); + function _lpDepositAll() internal virtual + { + + } + + function _lpWithdrawAll() internal virtual + { + + } + /** * Balancer returns assets and rateProviders for corresponding assets ordered * by numerical order. @@ -141,6 +156,53 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { return tokens; } + /** + * Balancer pools might have wrapped versions of assets that the strategy + * is handling. This function takes care of the conversion: + * strategy asset -> pool asset + */ + function toPoolAsset(address asset, uint256 amount) + view + internal + returns(address poolAsset, uint256 poolAmount) + { + // if stEth + if (asset == 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84) { + // wstEth + poolAsset = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; + poolAmount = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0).getWstETHByStETH(amount); + // if frxEth + } else if (asset == 0x5E8422345238F34275888049021821E8E08CAa1f) { + // sfrxEth + poolAsset = 0xac3E018457B222d93114458476f3E3416Abbe38F; + poolAmount = IERC4626(0xac3E018457B222d93114458476f3E3416Abbe38F).convertToShares(amount); + } else { + poolAsset = asset; + poolAmount = amount; + } + } + + function fromPoolAsset(address asset, uint256 amount) + view + internal + returns(address strategyAsset, uint256 strategyAmount) + { + // if wstEth + if (asset == 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0) { + // stEth + strategyAsset = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; + strategyAmount = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0).getStETHByWstETH(amount); + // if frxEth + } else if (asset == 0xac3E018457B222d93114458476f3E3416Abbe38F) { + // sfrxEth + strategyAsset = 0x5E8422345238F34275888049021821E8E08CAa1f; + strategyAmount = IERC4626(0xac3E018457B222d93114458476f3E3416Abbe38F).convertToAssets(amount); + } else { + strategyAsset = asset; + strategyAmount = amount; + } + } + /** * @dev Sets max withdrawal slippage that is considered when removing * liquidity from Balancer pools. diff --git a/contracts/deploy/043_convexOUSDMeta.js b/contracts/deploy/043_convexOUSDMeta.js index f6db5dbae2..b34ba339ec 100644 --- a/contracts/deploy/043_convexOUSDMeta.js +++ b/contracts/deploy/043_convexOUSDMeta.js @@ -99,7 +99,7 @@ module.exports = deploymentWithProposal( await withConfirmation( cConvexOUSDMetaStrategy .connect(sDeployer) - .transferGovernance(governorAddr, await getTxOpts()) + .transferGovernance(addresses.mainnet.Timelock, await getTxOpts()) ); console.log( diff --git a/contracts/deploy/071_balancer_wstETH_WETH.js b/contracts/deploy/071_balancer_wstETH_WETH.js new file mode 100644 index 0000000000..92664c28f6 --- /dev/null +++ b/contracts/deploy/071_balancer_wstETH_WETH.js @@ -0,0 +1,145 @@ +const { deploymentWithGovernanceProposal } = require("../utils/deploy"); +const addresses = require("../utils/addresses"); +const { BigNumber } = require("ethers"); +const { balancerWstEthWethPID } = require("../utils/constants"); + +module.exports = deploymentWithGovernanceProposal( + { + deployName: "071_balancer_wstETH_WETH", + forceDeploy: false, + deployerIsProposer: true, + //proposalId: , + }, + async ({ + assetAddresses, + deployWithConfirmation, + ethers, + getTxOpts, + withConfirmation, + }) => { + const { deployerAddr, governorAddr } = await getNamedAccounts(); + const sDeployer = await ethers.provider.getSigner(deployerAddr); + + // Current contracts + const cOETHVaultProxy = await ethers.getContract("OETHVaultProxy"); + const cOETHVaultAdmin = await ethers.getContractAt( + "OETHVaultAdmin", + cOETHVaultProxy.address + ); + const cOETHVault = await ethers.getContractAt("OETHVault", cOETHVaultProxy.address); + + // Deployer Actions + // ---------------- + + // 1. Deploy new proxy + // New strategy will be living at a clean address + const dOETHBalancerMetaPoolStrategyProxy = await deployWithConfirmation( + "OETHBalancerMetaPoolStrategyProxy" + ); + const cOETHBalancerMetaPoolStrategyProxy = await ethers.getContractAt( + "OETHBalancerMetaPoolStrategyProxy", + dOETHBalancerMetaPoolStrategyProxy.address + ); + + // 2. Deploy new implementation + const dOETHBalancerMetaPoolStrategyImpl = await deployWithConfirmation( + "BalancerMetaPoolStrategy" + ); + const cOETHBalancerMetaPoolStrategy = await ethers.getContractAt( + "BalancerMetaPoolStrategy", + dOETHBalancerMetaPoolStrategyProxy.address + ); + + const cOETHHarvesterProxy = await ethers.getContract("OETHHarvesterProxy"); + const cOETHHarvester = await ethers.getContractAt( + "OETHHarvester", + cOETHHarvesterProxy.address + ); + + // 3. Init the proxy to point at the implementation + await withConfirmation( + cOETHBalancerMetaPoolStrategyProxy + .connect(sDeployer) + ["initialize(address,address,bytes)"]( + dOETHBalancerMetaPoolStrategyImpl.address, + sDeployer.address, + [], + await getTxOpts() + ) + ); + + // 4. Init and configure new Convex OUSD Meta strategy + const initFunction = + "initialize(address[],address[],address[],(address,address,address,address,uint256,bytes32))"; + await withConfirmation( + cOETHBalancerMetaPoolStrategy.connect(sDeployer)[initFunction]( + [addresses.mainnet.BAL, addresses.mainnet.AURA], + [addresses.mainnet.stETH, addresses.mainnet.WETH], + [ + addresses.mainnet.wstETH_WETH_BPT, + addresses.mainnet.wstETH_WETH_BPT + ], + [ + addresses.mainnet.wstETH_WETH_BPT, + cOETHVaultProxy.address, + addresses.mainnet.aureDepositor, // auraDepositorAddress, + addresses.mainnet.CurveOUSDMetaPool, // auraRewardStakerAddress + balancerWstEthWethPID, // auraDepositorPTokenId + "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080" + ], + await getTxOpts() + ) + ); + + console.log("INIT DONE"); + + await withConfirmation( + cOETHBalancerMetaPoolStrategy + .connect(sDeployer) + .transferGovernance(addresses.mainnet.Timelock, await getTxOpts()) + ); + + console.log( + "BALANCER STRATEGY ADDRESS", + dOETHBalancerMetaPoolStrategyProxy.address + ); + + // Governance Actions + // ---------------- + return { + name: "Deploy new Balancer MetaPool strategy", + actions: [ + // 1. Accept governance of the new strategy + { + contract: cOETHBalancerMetaPoolStrategy, + signature: "claimGovernance()", + args: [], + }, + // 2. Add new strategy to the vault + { + contract: cOETHVaultAdmin, + signature: "approveStrategy(address)", + args: [cOETHBalancerMetaPoolStrategy.address], + }, + // 3. Set OUSD meta strategy on Vault Admin contract + { + contract: cOETHVaultAdmin, + signature: "setOusdMetaStrategy(address)", + args: [cOETHBalancerMetaPoolStrategy.address], + }, + // 4. Set supported strategy on Harvester + { + contract: cOETHHarvester, + signature: "setSupportedStrategy(address,bool)", + args: [cOETHBalancerMetaPoolStrategy.address, true], + }, + // 5. Set harvester address + { + contract: cOETHBalancerMetaPoolStrategy, + signature: "setHarvesterAddress(address)", + args: [cOETHHarvesterProxy.address], + }, + ], + }; + } +); diff --git a/contracts/utils/addresses.js b/contracts/utils/addresses.js index 1e19967958..26a0301be3 100644 --- a/contracts/utils/addresses.js +++ b/contracts/utils/addresses.js @@ -168,6 +168,11 @@ addresses.mainnet.OETHVaultProxy = "0x39254033945aa2e4809cc2977e7087bee48bd7ab"; addresses.mainnet.OETHZapper = "0x9858e47BCbBe6fBAC040519B02d7cd4B2C470C66"; addresses.mainnet.FraxETHStrategy = "0x3ff8654d633d4ea0fae24c52aec73b4a20d0d0e5"; +addresses.mainnet.BAL = "0xba100000625a3754423978a60c9317c58a424e3D"; +addresses.mainnet.AURA = "0xc0c293ce456ff0ed870add98a0828dd4d2903dbf"; +addresses.mainnet.wstETH = "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0"; +addresses.mainnet.wstETH_WETH_BPT = "0x32296969ef14eb0c6d29669c550d4a0449130230"; +addresses.mainnet.aureDepositor = "0x59d66c58e83a26d6a0e35114323f65c3945c89c1"; // Tokens addresses.mainnet.sfrxETH = "0xac3E018457B222d93114458476f3E3416Abbe38F"; diff --git a/contracts/utils/constants.js b/contracts/utils/constants.js index aa2508ea34..787d97751e 100644 --- a/contracts/utils/constants.js +++ b/contracts/utils/constants.js @@ -2,6 +2,7 @@ const threeCRVPid = 9; const metapoolLPCRVPid = 56; const lusdMetapoolLPCRVPid = 33; const oethPoolLpPID = 174; +const balancerWstEthWethPID = 115; const { BigNumber } = require("ethers"); const MAX_UINT256 = BigNumber.from( "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" @@ -13,6 +14,7 @@ module.exports = { lusdMetapoolLPCRVPid, oethPoolLpPID, MAX_UINT256, + balancerWstEthWethPID }; // These are all the metapool ids. For easier future reference From 632250735640af7fe6987b8dfd6d58420083774f Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Fri, 14 Jul 2023 17:00:56 +0200 Subject: [PATCH 09/67] add deployment file --- .../balancer/BaseBalancerStrategy.sol | 9 +-- contracts/deploy/071_balancer_wstETH_WETH.js | 73 +++++++------------ 2 files changed, 30 insertions(+), 52 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 0cd97538a7..42084270a9 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -17,12 +17,13 @@ import "hardhat/console.sol"; abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { using SafeERC20 for IERC20; + IBalancerVault internal immutable balancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); + address internal auraDepositorAddress; address internal auraRewardStakerAddress; uint256 internal auraDepositorPTokenId; address internal pTokenAddress; bytes32 internal balancerPoolId; - IBalancerVault internal balancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) uint256 public maxWithdrawalSlippage; int256[50] private __reserved; @@ -58,22 +59,20 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { address[] calldata _pTokens, InitConfig calldata initConfig ) external onlyGovernor initializer { - console.log("sol 1"); auraDepositorAddress = initConfig.auraDepositorAddress; auraRewardStakerAddress = initConfig.auraRewardStakerAddress; auraDepositorPTokenId = initConfig.auraDepositorPTokenId; pTokenAddress = _pTokens[0]; maxWithdrawalSlippage = 1e15; balancerPoolId = initConfig.balancerPoolId; - console.log("sol 2"); IERC20[] memory poolAssets = getPoolAssets(); uint256 assetsLength = _assets.length; require (poolAssets.length == assetsLength, "Pool assets and _assets should be the same length."); for (uint256 i = 0; i < assetsLength; ++i) { - require(_assets[i] == address(poolAssets[i]), "Pool assets and _assets should all have the same numerical order."); + (address strategyAsset, ) = fromPoolAsset(address(poolAssets[i]), 0); + require(_assets[i] == strategyAsset, "Pool assets and _assets should all have the same numerical order."); } - console.log("sol 3"); super._initialize( initConfig.platformAddress, initConfig.vaultAddress, diff --git a/contracts/deploy/071_balancer_wstETH_WETH.js b/contracts/deploy/071_balancer_wstETH_WETH.js index 92664c28f6..6cae1cb9a7 100644 --- a/contracts/deploy/071_balancer_wstETH_WETH.js +++ b/contracts/deploy/071_balancer_wstETH_WETH.js @@ -56,49 +56,40 @@ module.exports = deploymentWithGovernanceProposal( cOETHHarvesterProxy.address ); - // 3. Init the proxy to point at the implementation + // 3. Encode the init data + const initFunction = + "initialize(address[],address[],address[],(address,address,address,address,uint256,bytes32))"; + const initData = cOETHBalancerMetaPoolStrategy.interface.encodeFunctionData(initFunction, [ + [addresses.mainnet.BAL, addresses.mainnet.AURA], + [addresses.mainnet.stETH, addresses.mainnet.WETH], + [ + addresses.mainnet.wstETH_WETH_BPT, + addresses.mainnet.wstETH_WETH_BPT + ], + [ + addresses.mainnet.wstETH_WETH_BPT, + cOETHVaultProxy.address, + addresses.mainnet.aureDepositor, // auraDepositorAddress, + addresses.mainnet.CurveOUSDMetaPool, // auraRewardStakerAddress + balancerWstEthWethPID, // auraDepositorPTokenId + "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080" + ] + ]); + + // 4. Init the proxy to point at the implementation await withConfirmation( cOETHBalancerMetaPoolStrategyProxy .connect(sDeployer) ["initialize(address,address,bytes)"]( dOETHBalancerMetaPoolStrategyImpl.address, - sDeployer.address, - [], + addresses.mainnet.Timelock, + initData, await getTxOpts() ) ); - // 4. Init and configure new Convex OUSD Meta strategy - const initFunction = - "initialize(address[],address[],address[],(address,address,address,address,uint256,bytes32))"; - await withConfirmation( - cOETHBalancerMetaPoolStrategy.connect(sDeployer)[initFunction]( - [addresses.mainnet.BAL, addresses.mainnet.AURA], - [addresses.mainnet.stETH, addresses.mainnet.WETH], - [ - addresses.mainnet.wstETH_WETH_BPT, - addresses.mainnet.wstETH_WETH_BPT - ], - [ - addresses.mainnet.wstETH_WETH_BPT, - cOETHVaultProxy.address, - addresses.mainnet.aureDepositor, // auraDepositorAddress, - addresses.mainnet.CurveOUSDMetaPool, // auraRewardStakerAddress - balancerWstEthWethPID, // auraDepositorPTokenId - "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080" - ], - await getTxOpts() - ) - ); - console.log("INIT DONE"); - await withConfirmation( - cOETHBalancerMetaPoolStrategy - .connect(sDeployer) - .transferGovernance(addresses.mainnet.Timelock, await getTxOpts()) - ); - console.log( "BALANCER STRATEGY ADDRESS", dOETHBalancerMetaPoolStrategyProxy.address @@ -109,31 +100,19 @@ module.exports = deploymentWithGovernanceProposal( return { name: "Deploy new Balancer MetaPool strategy", actions: [ - // 1. Accept governance of the new strategy - { - contract: cOETHBalancerMetaPoolStrategy, - signature: "claimGovernance()", - args: [], - }, - // 2. Add new strategy to the vault + // 1. Add new strategy to the vault { contract: cOETHVaultAdmin, signature: "approveStrategy(address)", args: [cOETHBalancerMetaPoolStrategy.address], }, - // 3. Set OUSD meta strategy on Vault Admin contract - { - contract: cOETHVaultAdmin, - signature: "setOusdMetaStrategy(address)", - args: [cOETHBalancerMetaPoolStrategy.address], - }, - // 4. Set supported strategy on Harvester + // 2. Set supported strategy on Harvester { contract: cOETHHarvester, signature: "setSupportedStrategy(address,bool)", args: [cOETHBalancerMetaPoolStrategy.address, true], }, - // 5. Set harvester address + // 3. Set harvester address { contract: cOETHBalancerMetaPoolStrategy, signature: "setHarvesterAddress(address)", From 5150986b6725a365899bc370ed0a958fa3458670 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Fri, 14 Jul 2023 17:10:38 +0200 Subject: [PATCH 10/67] add fork test fixture --- contracts/contracts/proxies/Proxies.sol | 2 +- contracts/deploy/071_balancer_wstETH_WETH.js | 4 +- contracts/test/_fixture.js | 46 ++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/contracts/contracts/proxies/Proxies.sol b/contracts/contracts/proxies/Proxies.sol index 9888b2ec22..936692ee20 100644 --- a/contracts/contracts/proxies/Proxies.sol +++ b/contracts/contracts/proxies/Proxies.sol @@ -160,6 +160,6 @@ contract OETHMorphoAaveStrategyProxy is InitializeGovernedUpgradeabilityProxy { /** * @notice OETHBalancerMetaPoolStrategyProxy delegates calls to a BalancerMetaPoolStrategy implementation */ -contract OETHBalancerMetaPoolStrategyProxy is InitializeGovernedUpgradeabilityProxy { +contract OETHBalancerMetaPoolWstEthWethStrategyProxy is InitializeGovernedUpgradeabilityProxy { } diff --git a/contracts/deploy/071_balancer_wstETH_WETH.js b/contracts/deploy/071_balancer_wstETH_WETH.js index 6cae1cb9a7..d5c2b57852 100644 --- a/contracts/deploy/071_balancer_wstETH_WETH.js +++ b/contracts/deploy/071_balancer_wstETH_WETH.js @@ -34,10 +34,10 @@ module.exports = deploymentWithGovernanceProposal( // 1. Deploy new proxy // New strategy will be living at a clean address const dOETHBalancerMetaPoolStrategyProxy = await deployWithConfirmation( - "OETHBalancerMetaPoolStrategyProxy" + "OETHBalancerMetaPoolWstEthWethStrategyProxy" ); const cOETHBalancerMetaPoolStrategyProxy = await ethers.getContractAt( - "OETHBalancerMetaPoolStrategyProxy", + "OETHBalancerMetaPoolWstEthWethStrategyProxy", dOETHBalancerMetaPoolStrategyProxy.address ); diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index c437633ca1..2590a47229 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -162,6 +162,7 @@ const defaultFixture = deployments.createFixture(async () => { morpho, morphoCompoundStrategy, fraxEthStrategy, + balancerWstEthWethStrategy, morphoAaveStrategy, oethMorphoAaveStrategy, morphoLens, @@ -265,6 +266,14 @@ const defaultFixture = deployments.createFixture(async () => { fraxEthStrategyProxy.address ); + const balancerWstEthWethStrategyProxy = await ethers.getContract( + "OETHBalancerMetaPoolWstEthWethStrategyProxy" + ); + balancerWstEthWethStrategy = await ethers.getContractAt( + "OETHBalancerMetaPoolStrategy", + balancerWstEthWethStrategyProxy.address + ); + const oethHarvesterProxy = await ethers.getContract("OETHHarvesterProxy"); oethHarvester = await ethers.getContractAt( "OETHHarvester", @@ -540,6 +549,7 @@ const defaultFixture = deployments.createFixture(async () => { frxETH, sfrxETH, fraxEthStrategy, + balancerWstEthWethStrategy, oethMorphoAaveStrategy, woeth, ConvexEthMetaStrategy, @@ -818,6 +828,42 @@ async function convexVaultFixture() { return fixture; } +/** + * Configure a Vault with only the balancerWstEthWethStrategy + */ +async function balancerWstEthWethFixture() { + const fixture = await loadFixture(defaultFixture); + const { oethVault, timelock, weth, balancerWstEthWethStrategy } = fixture; + + const sTimelock = await ethers.provider.getSigner(timelock); + + await fixture.oethVault + .connect(sTimelock) + .setAssetDefaultStrategy( + fixture.weth.address, + fixture.balancerWstEthWethStrategy.address + ); + await fixture.oethVault + .connect(sTimelock) + .setAssetDefaultStrategy( + fixture.stETH.address, + fixture.balancerWstEthWethStrategy.address + ); + await fixture.oethVault + .connect(sTimelock) + .setAssetDefaultStrategy( + fixture.weth.address, + fixture.balancerWstEthWethStrategy.address + ); + await fixture.oethVault + .connect(sTimelock) + .setAssetDefaultStrategy( + fixture.stETH.address, + fixture.balancerWstEthWethStrategy.address + ); + return fixture; +} + async function fundWith3Crv(address, maxAmount) { // Get some 3CRV from most loaded contracts/wallets await impersonateAndFundAddress( From fa5838b52d91847564799d3c5ed410f68aed3bd5 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Tue, 18 Jul 2023 11:35:36 +0200 Subject: [PATCH 11/67] intermittent commit --- contracts/contracts/interfaces/IWstETH.sol | 25 +++++- .../balancer/BalancerMetaPoolStrategy.sol | 46 +++++++++- .../balancer/BaseBalancerStrategy.sol | 35 +++++++- contracts/deploy/071_balancer_wstETH_WETH.js | 4 +- contracts/test/_fixture.js | 13 ++- .../balancerMetaStablePool.fork-test.js | 84 +++++++++++++++++++ 6 files changed, 193 insertions(+), 14 deletions(-) create mode 100644 contracts/test/strategies/balancerMetaStablePool.fork-test.js diff --git a/contracts/contracts/interfaces/IWstETH.sol b/contracts/contracts/interfaces/IWstETH.sol index b35d04df24..ec9875d93c 100644 --- a/contracts/contracts/interfaces/IWstETH.sol +++ b/contracts/contracts/interfaces/IWstETH.sol @@ -25,5 +25,28 @@ interface IWstETH { * @notice Get amount of wstETH for a one stETH * @return Amount of wstETH for a 1 stETH */ - function tokensPerStEth() external view returns (uint256); + function tokensPerStEth() external view returns (uint256); + + /** + * @notice Exchanges stETH to wstETH + * @param _stETHAmount amount of stETH to wrap in exchange for wstETH + * @dev Requirements: + * - `_stETHAmount` must be non-zero + * - msg.sender must approve at least `_stETHAmount` stETH to this + * contract. + * - msg.sender must have at least `_stETHAmount` of stETH. + * User should first approve _stETHAmount to the WstETH contract + * @return Amount of wstETH user receives after wrap + */ + function wrap(uint256 _stETHAmount) external returns (uint256); + + /** + * @notice Exchanges wstETH to stETH + * @param _wstETHAmount amount of wstETH to uwrap in exchange for stETH + * @dev Requirements: + * - `_wstETHAmount` must be non-zero + * - msg.sender must have at least `_wstETHAmount` wstETH. + * @return Amount of stETH user receives after unwrap + */ + function unwrap(uint256 _wstETHAmount) external returns (uint256); } \ No newline at end of file diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 648b57bbea..26b51981b6 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -4,13 +4,20 @@ pragma solidity ^0.8.0; * @title OETH Balancer MetaStablePool Strategy * @author Origin Protocol Inc */ +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { BaseBalancerStrategy } from "./BaseBalancerStrategy.sol"; import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { IMetaStablePool } from "../../interfaces/balancer/IMetaStablePool.sol"; import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; +import "hardhat/console.sol"; contract BalancerMetaPoolStrategy is BaseBalancerStrategy { + using SafeERC20 for IERC20; + address immutable internal stETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; + address immutable internal wstETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; + address immutable internal frxETH = 0x5E8422345238F34275888049021821E8E08CAa1f; + address immutable internal sfrxETH = 0xac3E018457B222d93114458476f3E3416Abbe38F; function getRateProviderRate(address _asset) internal @@ -25,6 +32,10 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { for (uint256 i = 0; i < providersLength; ++i) { // _assets and corresponding rate providers are all in the same order if (assetsMapped[i] == _asset) { + // rate provider doesn't exist, defaults to 1e18 + if (address(providers[i]) == address(0)) { + return 1e18; + } return providers[i].getRate(); } } @@ -85,6 +96,14 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { } } + wrapPoolAsset(_asset, _amount); + + console.log("xxx"); + console.log(_amount); + console.log(_asset); + console.log(getMinBPTExpected(_asset, _amount)); + // TODO wrap the tokens + /* TOKEN_IN_FOR_EXACT_BPT_OUT: * User sends an estimated but unknown (computed at run time) quantity of a single token, * and receives a precise quantity of BPT. @@ -92,9 +111,11 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { * ['uint256', 'uint256', 'uint256'] * [TOKEN_IN_FOR_EXACT_BPT_OUT, bptAmountOut, enterTokenIndex] */ - bytes memory userData = abi.encode(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, getMinBPTExpected(poolAsset, poolAmount), assetIndex); + //bytes memory userData = abi.encode(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, getMinBPTExpected(_asset, _amount), assetIndex); + bytes memory userData = abi.encode(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, 0, assetIndex); IBalancerVault.JoinPoolRequest memory request = IBalancerVault.JoinPoolRequest(joinPoolAssets, maxAmountsIn, userData, false); + console.log(IERC20(platformAddress).balanceOf(address(this))); balancerVault.joinPool(balancerPoolId, address(this), address(this), request); _lpDepositAll(); @@ -106,11 +127,32 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { onlyGovernor nonReentrant { + for (uint256 i = 0; i < assetsMapped.length; i++) { + _approveAsset(assetsMapped[i]); + } + _approveBase(); } function _abstractSetPToken(address _asset, address _pToken) internal override - {} + { + (address poolAsset,) = toPoolAsset(_asset, 0); + // stEth + if (_asset == stETH) { + IERC20(stETH).approve(wstETH, 1e50); + // if frxEth + } else if (_asset == frxETH) { + IERC20(frxETH).approve(sfrxETH, 1e50); + } + _approveAsset(poolAsset); + } + + function _approveAsset(address _asset) internal { + IERC20 asset = IERC20(_asset); + // 3Pool for asset (required for adding liquidity) + asset.safeApprove(address(balancerVault), 0); + asset.safeApprove(address(balancerVault), type(uint256).max); + } } \ No newline at end of file diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 42084270a9..95a723e1f5 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -13,10 +13,13 @@ import { IOracle } from "../../interfaces/IOracle.sol"; import { IVault } from "../../interfaces/IVault.sol"; import { IWstETH } from "../../interfaces/IWstETH.sol"; import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; +import { StableMath } from "../../utils/StableMath.sol"; + import "hardhat/console.sol"; abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { using SafeERC20 for IERC20; + using StableMath for uint256; IBalancerVault internal immutable balancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); address internal auraDepositorAddress; @@ -127,7 +130,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256 rateProviderRate = getRateProviderRate(_asset); // TODO: account for some slippage? - return marketPrice / rateProviderRate; + return marketPrice.divPrecisely(rateProviderRate); } function getRateProviderRate(address _asset) internal virtual view returns(uint256); @@ -181,6 +184,36 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } } + function wrapPoolAsset(address asset, uint256 amount) + internal + returns(uint256 wrappedAmount) + { + // if stEth + if (asset == 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84) { + wrappedAmount = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0).wrap(amount); + // if frxEth + } else if (asset == 0x5E8422345238F34275888049021821E8E08CAa1f) { + wrappedAmount = IERC4626(0xac3E018457B222d93114458476f3E3416Abbe38F).deposit(amount, address(this)); + } else { + wrappedAmount = amount; + } + } + + function unwrapPoolAsset(address asset, uint256 amount) + internal + returns(uint256 wrappedAmount) + { + // if stEth + if (asset == 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84) { + wrappedAmount = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0).unwrap(amount); + // if frxEth + } else if (asset == 0x5E8422345238F34275888049021821E8E08CAa1f) { + wrappedAmount = IERC4626(0xac3E018457B222d93114458476f3E3416Abbe38F).withdraw(amount, address(this), address(this)); + } else { + wrappedAmount = amount; + } + } + function fromPoolAsset(address asset, uint256 amount) view internal diff --git a/contracts/deploy/071_balancer_wstETH_WETH.js b/contracts/deploy/071_balancer_wstETH_WETH.js index d5c2b57852..402c3dc9d0 100644 --- a/contracts/deploy/071_balancer_wstETH_WETH.js +++ b/contracts/deploy/071_balancer_wstETH_WETH.js @@ -88,10 +88,8 @@ module.exports = deploymentWithGovernanceProposal( ) ); - console.log("INIT DONE"); - console.log( - "BALANCER STRATEGY ADDRESS", + "Balancer strategy address:", dOETHBalancerMetaPoolStrategyProxy.address ); diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 2590a47229..8fab3f3209 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -270,7 +270,7 @@ const defaultFixture = deployments.createFixture(async () => { "OETHBalancerMetaPoolWstEthWethStrategyProxy" ); balancerWstEthWethStrategy = await ethers.getContractAt( - "OETHBalancerMetaPoolStrategy", + "BalancerMetaPoolStrategy", balancerWstEthWethStrategyProxy.address ); @@ -835,28 +835,26 @@ async function balancerWstEthWethFixture() { const fixture = await loadFixture(defaultFixture); const { oethVault, timelock, weth, balancerWstEthWethStrategy } = fixture; - const sTimelock = await ethers.provider.getSigner(timelock); - await fixture.oethVault - .connect(sTimelock) + .connect(timelock) .setAssetDefaultStrategy( fixture.weth.address, fixture.balancerWstEthWethStrategy.address ); await fixture.oethVault - .connect(sTimelock) + .connect(timelock) .setAssetDefaultStrategy( fixture.stETH.address, fixture.balancerWstEthWethStrategy.address ); await fixture.oethVault - .connect(sTimelock) + .connect(timelock) .setAssetDefaultStrategy( fixture.weth.address, fixture.balancerWstEthWethStrategy.address ); await fixture.oethVault - .connect(sTimelock) + .connect(timelock) .setAssetDefaultStrategy( fixture.stETH.address, fixture.balancerWstEthWethStrategy.address @@ -1662,6 +1660,7 @@ module.exports = { impersonateAndFundContract, impersonateAccount, fraxETHStrategyFixtureSetup, + balancerWstEthWethFixture, oethMorphoAaveFixtureSetup, mintWETH, replaceContractAt, diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js new file mode 100644 index 0000000000..c513027055 --- /dev/null +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -0,0 +1,84 @@ +const { expect } = require("chai"); + +const { loadFixture } = require("ethereum-waffle"); +const { + units, + ousdUnits, + forkOnlyDescribe, + advanceBlocks, + advanceTime, +} = require("../helpers"); +const { + balancerWstEthWethFixture, + impersonateAndFundContract, +} = require("../_fixture"); + +forkOnlyDescribe("ForkTest: Balancer MetaStablePool stWeth/WETH Strategy", function () { + this.timeout(0); + // due to hardhat forked mode timeouts - retry failed tests up to 3 times + this.retries(3); + + let fixture; + beforeEach(async () => { + fixture = await loadFixture(balancerWstEthWethFixture); + }); + + describe.only("Mint", function () { + it("Should deploy WETH in Balancer MetaStablePool strategy", async function () { + const { josh, weth } = fixture; + await mintTest(fixture, josh, weth, "30"); + }); + + it("Should deploy stETH in Balancer MetaStablePool strategy", async function () { + const { josh, stETH } = fixture; + await mintTest(fixture, josh, stETH, "30"); + }); + }); + + // set it as a last test that executes because we advance time and theat + // messes with recency of oracle prices + describe("Supply Revenue", function () { + + }); +}); + +async function mintTest(fixture, user, asset, amount = "30000") { + const { oethVault, oeth, balancerWstEthWethStrategy } = fixture; + + await oethVault.connect(user).allocate(); + + const unitAmount = await units(amount, asset); + + const currentSupply = await oeth.totalSupply(); + const currentBalance = await oeth.connect(user).balanceOf(user.address); + const currentBalancerBalance = await balancerWstEthWethStrategy.checkBalance( + asset.address + ); + + // Mint OETH w/ asset + await oethVault.connect(user).mint(asset.address, unitAmount, 0); + await oethVault.connect(user).allocate(); + + const newBalance = await oeth.connect(user).balanceOf(user.address); + const newSupply = await oeth.totalSupply(); + const newBalancerBalance = await balancerWstEthWethStrategy.checkBalance(asset.address); + + const balanceDiff = newBalance.sub(currentBalance); + // Ensure user has correct balance (w/ 1% slippage tolerance) + expect(balanceDiff).to.approxEqualTolerance(ousdUnits(amount), 2); + + // Supply checks + const supplyDiff = newSupply.sub(currentSupply); + const ousdUnitAmount = ousdUnits(amount); + + expect(supplyDiff).to.approxEqualTolerance(ousdUnitAmount, 1); + + const balancerLiquidityDiff = newBalancerBalance.sub(currentBalancerBalance); + + // Should have liquidity in Morpho + expect(balancerLiquidityDiff).to.approxEqualTolerance( + await units(amount, asset), + 1 + ); +} + From 74f14036f5bc722feb79d6663e5ef84bccb950de Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 20 Jul 2023 21:37:08 +0200 Subject: [PATCH 12/67] prettier --- brownie/playingAround.py | 51 ++-- contracts/contracts/interfaces/IWstETH.sol | 12 +- .../interfaces/balancer/IBalancerVault.sol | 18 +- .../interfaces/balancer/IMetaStablePool.sol | 7 +- .../interfaces/balancer/IRateProvider.sol | 2 +- contracts/contracts/proxies/Proxies.sol | 4 +- .../balancer/BalancerMetaPoolStrategy.sol | 112 +++++--- .../strategies/balancer/BaseAuraStrategy.sol | 115 ++++++++ .../balancer/BaseBalancerStrategy.sol | 262 +++++++++--------- contracts/deploy/071_balancer_wstETH_WETH.js | 34 ++- .../balancerMetaStablePool.fork-test.js | 73 +++-- contracts/utils/addresses.js | 5 +- contracts/utils/constants.js | 2 +- 13 files changed, 446 insertions(+), 251 deletions(-) create mode 100644 contracts/contracts/strategies/balancer/BaseAuraStrategy.sol diff --git a/brownie/playingAround.py b/brownie/playingAround.py index ccb7b9893e..e6ac1f85b3 100644 --- a/brownie/playingAround.py +++ b/brownie/playingAround.py @@ -24,6 +24,8 @@ # MANAGEMENT_FEE_TOKENS_OUT // for InvestmentPool # } +#addresses.mainnet.aureDepositor = "0x59d66c58e83a26d6a0e35114323f65c3945c89c1"; + # wstETH / WETH pool_id = "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080" ba_vault=Contract.from_explorer("0xBA12222222228d8Ba445958a75a0704d566BF2C8") @@ -46,24 +48,39 @@ weth.approve(ba_vault, 10**36, STD) wsteth.approve(ba_vault, 10**36, STD) -# Enter the pool -ba_vault.joinPool( - pool_id, - vault_oeth_admin.address, #sender - vault_oeth_admin.address, #recipient - [ - # tokens need to be sorted numerically - [wsteth.address, weth.address], # assets - # indexes match above assets - [10*10**18, 10*10**18], # min amounts in - # userData = balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(2, 5*10**18, 1) - '0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000001', # userData - False, #fromInternalBalance - ], - STD -) +with TemporaryFork(): + # Enter the pool + ba_vault.joinPool( + pool_id, + vault_oeth_admin.address, #sender + vault_oeth_admin.address, #recipient + [ + # tokens need to be sorted numerically + [wsteth.address, weth.address], # assets + # indexes match above assets + [0, 36523558823496626525], # min amounts in + # balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(2, 36158323235261660260, 1)[10:] + # balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(2, 123, 1)[10:] + balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(2, 36158323235261660260 * 0.97, 1)[10:], + False, #fromInternalBalance + ], + STD + ) + bpt_balance = wstETHPool.balanceOf(vault_oeth_admin) + print("BPT BALANCE: ", bpt_balance) + + wstETHPool.approve(rewardPool.address, 1e50, STD) + rewardPool.deposit(bpt_balance, oeth_vault_admin, STD) + + aura_balance = rewardPool.balanceOf(vault_oeth_admin.address, STD) + print("BPT BALANCE AURA: ", aura_balance) + + # WITHDRAW FROM AURA + rewardPool.withdraw(aura_balance, oeth_vault_admin, oeth_vault_admin, STD) + + bpt_balance = wstETHPool.balanceOf(vault_oeth_admin) + print("BPT BALANCE AFTER AURA: ", bpt_balance) -bpt_balance = wstETHPool.balanceOf(vault_oeth_admin) # Exit the pool ba_vault.exitPool( diff --git a/contracts/contracts/interfaces/IWstETH.sol b/contracts/contracts/interfaces/IWstETH.sol index ec9875d93c..467a81c297 100644 --- a/contracts/contracts/interfaces/IWstETH.sol +++ b/contracts/contracts/interfaces/IWstETH.sol @@ -6,14 +6,20 @@ interface IWstETH { * @param _stETHAmount amount of stETH * @return Amount of wstETH for a given stETH amount */ - function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256); + function getWstETHByStETH(uint256 _stETHAmount) + external + view + returns (uint256); /** * @notice Get amount of stETH for a given amount of wstETH * @param _wstETHAmount amount of wstETH * @return Amount of stETH for a given wstETH amount */ - function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256); + function getStETHByWstETH(uint256 _wstETHAmount) + external + view + returns (uint256); /** * @notice Get amount of stETH for a one wstETH @@ -49,4 +55,4 @@ interface IWstETH { * @return Amount of stETH user receives after unwrap */ function unwrap(uint256 _wstETHAmount) external returns (uint256); -} \ No newline at end of file +} diff --git a/contracts/contracts/interfaces/balancer/IBalancerVault.sol b/contracts/contracts/interfaces/balancer/IBalancerVault.sol index 304b36d5c4..499837a9a5 100644 --- a/contracts/contracts/interfaces/balancer/IBalancerVault.sol +++ b/contracts/contracts/interfaces/balancer/IBalancerVault.sol @@ -5,18 +5,18 @@ import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; interface IBalancerVault { enum WeightedPoolJoinKind { - INIT, - EXACT_TOKENS_IN_FOR_BPT_OUT, - TOKEN_IN_FOR_EXACT_BPT_OUT, - ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, - ADD_TOKEN + INIT, + EXACT_TOKENS_IN_FOR_BPT_OUT, + TOKEN_IN_FOR_EXACT_BPT_OUT, + ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, + ADD_TOKEN } enum WeightedPoolExitKind { - EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, - EXACT_BPT_IN_FOR_TOKENS_OUT, - BPT_IN_FOR_EXACT_TOKENS_OUT, - REMOVE_TOKEN + EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, + EXACT_BPT_IN_FOR_TOKENS_OUT, + BPT_IN_FOR_EXACT_TOKENS_OUT, + REMOVE_TOKEN } /** diff --git a/contracts/contracts/interfaces/balancer/IMetaStablePool.sol b/contracts/contracts/interfaces/balancer/IMetaStablePool.sol index 74d622a65a..760737359f 100644 --- a/contracts/contracts/interfaces/balancer/IMetaStablePool.sol +++ b/contracts/contracts/interfaces/balancer/IMetaStablePool.sol @@ -4,5 +4,8 @@ pragma solidity ^0.8.0; import { IRateProvider } from "./IRateProvider.sol"; interface IMetaStablePool { - function getRateProviders() external view returns (IRateProvider[] memory providers); -} \ No newline at end of file + function getRateProviders() + external + view + returns (IRateProvider[] memory providers); +} diff --git a/contracts/contracts/interfaces/balancer/IRateProvider.sol b/contracts/contracts/interfaces/balancer/IRateProvider.sol index 21c461e7ab..29813706a9 100644 --- a/contracts/contracts/interfaces/balancer/IRateProvider.sol +++ b/contracts/contracts/interfaces/balancer/IRateProvider.sol @@ -17,4 +17,4 @@ pragma solidity ^0.8.0; // TODO: pull this from the monorepo interface IRateProvider { function getRate() external view returns (uint256); -} \ No newline at end of file +} diff --git a/contracts/contracts/proxies/Proxies.sol b/contracts/contracts/proxies/Proxies.sol index 936692ee20..898f958527 100644 --- a/contracts/contracts/proxies/Proxies.sol +++ b/contracts/contracts/proxies/Proxies.sol @@ -160,6 +160,8 @@ contract OETHMorphoAaveStrategyProxy is InitializeGovernedUpgradeabilityProxy { /** * @notice OETHBalancerMetaPoolStrategyProxy delegates calls to a BalancerMetaPoolStrategy implementation */ -contract OETHBalancerMetaPoolWstEthWethStrategyProxy is InitializeGovernedUpgradeabilityProxy { +contract OETHBalancerMetaPoolWstEthWethStrategyProxy is + InitializeGovernedUpgradeabilityProxy +{ } diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 26b51981b6..a58c90e1a8 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -5,39 +5,44 @@ pragma solidity ^0.8.0; * @author Origin Protocol Inc */ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { BaseBalancerStrategy } from "./BaseBalancerStrategy.sol"; +import { BaseAuraStrategy } from "./BaseAuraStrategy.sol"; import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { IMetaStablePool } from "../../interfaces/balancer/IMetaStablePool.sol"; import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; import "hardhat/console.sol"; -contract BalancerMetaPoolStrategy is BaseBalancerStrategy { + +contract BalancerMetaPoolStrategy is BaseAuraStrategy { using SafeERC20 for IERC20; - address immutable internal stETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; - address immutable internal wstETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; - address immutable internal frxETH = 0x5E8422345238F34275888049021821E8E08CAa1f; - address immutable internal sfrxETH = 0xac3E018457B222d93114458476f3E3416Abbe38F; + address internal immutable stETH = + 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; + address internal immutable wstETH = + 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; + address internal immutable frxETH = + 0x5E8422345238F34275888049021821E8E08CAa1f; + address internal immutable sfrxETH = + 0xac3E018457B222d93114458476f3E3416Abbe38F; function getRateProviderRate(address _asset) internal - override view - returns(uint256) + override + returns (uint256) { IMetaStablePool pool = IMetaStablePool(platformAddress); IRateProvider[] memory providers = pool.getRateProviders(); uint256 providersLength = providers.length; for (uint256 i = 0; i < providersLength; ++i) { - // _assets and corresponding rate providers are all in the same order - if (assetsMapped[i] == _asset) { - // rate provider doesn't exist, defaults to 1e18 - if (address(providers[i]) == address(0)) { - return 1e18; + // _assets and corresponding rate providers are all in the same order + if (poolAssetsMapped[i] == _asset) { + // rate provider doesn't exist, defaults to 1e18 + if (address(providers[i]) == address(0)) { + return 1e18; + } + return providers[i].getRate(); } - return providers[i].getRate(); - } } // should never happen @@ -48,14 +53,9 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { address _recipient, address _asset, uint256 _amount - ) external override onlyVault nonReentrant - { + ) external override onlyVault nonReentrant {} - } - - function withdrawAll() external override onlyVaultOrGovernor nonReentrant { - - } + function withdrawAll() external override onlyVaultOrGovernor nonReentrant {} function deposit(address _asset, uint256 _amount) external @@ -76,18 +76,25 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { } } - function _deposit(address _asset, uint256 _amount) - internal - { + function _deposit(address _asset, uint256 _amount) internal { + /* dust rounding issues with stETH. When allocate is called it tries + * to deposit 1-2 wei of stETH and the deposit fails with BPT amount check. + * + * TODO: solve this (only a problem when it is a default strategy for stETH) + */ + if (_asset == stEth && _amount < 20) { + return; + } + (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); - (IERC20[] memory tokens,,) = balancerVault.getPoolTokens(balancerPoolId); + (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( + balancerPoolId + ); uint256 tokensLength = tokens.length; uint256[] memory maxAmountsIn = new uint256[](tokensLength); uint256 assetIndex = 0; - address[] memory joinPoolAssets = new address[](tokensLength); for (uint256 i = 0; i < tokensLength; ++i) { - joinPoolAssets[i] = address(tokens[i]); if (address(tokens[i]) == poolAsset) { maxAmountsIn[i] = poolAmount; assetIndex = i; @@ -98,11 +105,23 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { wrapPoolAsset(_asset, _amount); - console.log("xxx"); - console.log(_amount); - console.log(_asset); - console.log(getMinBPTExpected(_asset, _amount)); - // TODO wrap the tokens + // console.log("xxx"); + // console.log(uint256(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT)); // 2 + // console.log(_amount); // 36523558823496626525 + // console.log(_asset); // 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 + // console.log("Max amounts in"); + // console.log(maxAmountsIn[0]); // 0 + // console.log(maxAmountsIn[1]); // 36523558823496626525 + + // TODO: figure out why the slippage is so high + uint256 minBPT = getMinBPTExpected( + _asset, + _amount, + poolAsset, + poolAmount + ); + // console.log("Min BPT expected"); + // console.log(minBPT); /* TOKEN_IN_FOR_EXACT_BPT_OUT: * User sends an estimated but unknown (computed at run time) quantity of a single token, @@ -111,12 +130,22 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { * ['uint256', 'uint256', 'uint256'] * [TOKEN_IN_FOR_EXACT_BPT_OUT, bptAmountOut, enterTokenIndex] */ - //bytes memory userData = abi.encode(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, getMinBPTExpected(_asset, _amount), assetIndex); - bytes memory userData = abi.encode(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, 0, assetIndex); - - IBalancerVault.JoinPoolRequest memory request = IBalancerVault.JoinPoolRequest(joinPoolAssets, maxAmountsIn, userData, false); + bytes memory userData = abi.encode( + IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, + minBPT, + assetIndex + ); + //bytes memory userData = abi.encode(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, 0, assetIndex); + + IBalancerVault.JoinPoolRequest memory request = IBalancerVault + .JoinPoolRequest(poolAssetsMapped, maxAmountsIn, userData, false); console.log(IERC20(platformAddress).balanceOf(address(this))); - balancerVault.joinPool(balancerPoolId, address(this), address(this), request); + balancerVault.joinPool( + balancerPoolId, + address(this), + address(this), + request + ); _lpDepositAll(); } @@ -137,11 +166,11 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { internal override { - (address poolAsset,) = toPoolAsset(_asset, 0); + (address poolAsset, ) = toPoolAsset(_asset, 0); // stEth if (_asset == stETH) { IERC20(stETH).approve(wstETH, 1e50); - // if frxEth + // if frxEth } else if (_asset == frxETH) { IERC20(frxETH).approve(sfrxETH, 1e50); } @@ -154,5 +183,4 @@ contract BalancerMetaPoolStrategy is BaseBalancerStrategy { asset.safeApprove(address(balancerVault), 0); asset.safeApprove(address(balancerVault), type(uint256).max); } - -} \ No newline at end of file +} diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol new file mode 100644 index 0000000000..66192acf41 --- /dev/null +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title OETH Base Balancer Abstract Strategy + * @author Origin Protocol Inc + */ +import { BaseBalancerStrategy } from "./BaseBalancerStrategy.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; +import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol";" + +import "hardhat/console.sol"; + +abstract contract BaseAuraStrategy is BaseBalancerStrategy { + using SafeERC20 for IERC20; + + address internal auraRewardPoolAddress; + address internal auraRewardStakerAddress; + uint256 internal auraDepositorPTokenId; + int256[50] private __reserved; + + struct InitConfig { + address platformAddress; // platformAddress Address of the Balancer's pool + address vaultAddress; // vaultAddress Address of the vault + address auraRewardPoolAddress; // auraRewardPoolAddress Address of the Aura rewards pool + address auraRewardStakerAddress; // auraRewardStakerAddress Address of the Aura rewards staker + uint256 auraDepositorPTokenId; // auraDepositorPTokenId Address of the Aura rewards staker + bytes32 balancerPoolId; // balancerPoolId bytes32 poolId + } + + /** + * Initializer for setting up strategy internal state. This overrides the + * InitializableAbstractStrategy initializer as Balancer's strategies don't fit + * well within that abstraction. + * @param _rewardTokenAddresses Address of BAL & AURA + * @param _assets Addresses of supported assets. MUST be passed in the same + * order as returned by coins on the pool contract, i.e. + * WETH, stETH + * @param _pTokens Platform Token corresponding addresses + * @param initConfig additional configuration + */ + function initialize( + address[] calldata _rewardTokenAddresses, // BAL & AURA + address[] calldata _assets, + address[] calldata _pTokens, + InitConfig calldata initConfig + ) external onlyGovernor initializer { + auraRewardPoolAddress = initConfig.auraRewardPoolAddress; + auraRewardStakerAddress = initConfig.auraRewardStakerAddress; + auraDepositorPTokenId = initConfig.auraDepositorPTokenId; + pTokenAddress = _pTokens[0]; + maxWithdrawalSlippage = 10e16; + balancerPoolId = initConfig.balancerPoolId; + IERC20[] memory poolAssets = getPoolAssets(); + uint256 assetsLength = _assets.length; + require (poolAssets.length == assetsLength, "Pool assets and _assets should be the same length."); + for (uint256 i = 0; i < assetsLength; ++i) { + (address asset, ) = fromPoolAsset(address(poolAssets[i]), 0); + require(_assets[i] == asset, "Pool assets and _assets should all have the same numerical order."); + // TODO: double check if this fits in here + poolAssetsMapped.push(address(poolAssets[i])); + } + + super._initialize( + initConfig.platformAddress, + initConfig.vaultAddress, + _rewardTokenAddresses, + _assets, + _pTokens + ); + _approveBase(); + } + + function _lpDepositAll() internal virtual override + { + uint256 bptBalance = IERC20(platformAddress).balanceOf(address(this)); + IERC4626(auraRewardPoolAddress).deposit(bptBalance); + } + + function _lpWithdrawAll() internal virtual override + { + + } + + function checkBalance(address _asset) + external + view + override + virtual + returns (uint256) + { + (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock) = balancerVault.getPoolTokens(balancerPoolId); + uint256 bptBalance = IERC20(pTokenAddress).balanceOf(address(this)) + IERC4626(auraRewardPoolAddress).balanceOf(address(this)); + // yourPoolShare denominated in 1e18. (1e18 == 100%) + uint256 yourPoolShare = IERC20(pTokenAddress).balanceOf(address(this)).divPrecisely(IERC20(pTokenAddress).totalSupply()); + + uint256 balancesLength = balances.length; + for (uint256 i=0; i < balances.length; ++i){ + (address poolAsset,) = toPoolAsset(_asset, 0); + if(address(tokens[i]) == poolAsset) { + return balances[i].mulTruncate(yourPoolShare); + } + } + } + + function _approveBase() internal virtual override { + super._approveBase(); + + IERC20 pToken = IERC20(pTokenAddress); + // Gauge for LP token + pToken.safeApprove(auraRewardPoolAddress, 0); + pToken.safeApprove(auraRewardPoolAddress, type(uint256).max); + } +} \ No newline at end of file diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 95a723e1f5..dcc9d41229 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -20,14 +20,22 @@ import "hardhat/console.sol"; abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { using SafeERC20 for IERC20; using StableMath for uint256; - IBalancerVault internal immutable balancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); + IBalancerVault internal immutable balancerVault = + IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); + address internal immutable stEth = + 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; + address internal immutable wstEth = + 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; + address internal immutable frxEth = + 0x5E8422345238F34275888049021821E8E08CAa1f; + address internal immutable sfrxEth = + 0xac3E018457B222d93114458476f3E3416Abbe38F; - address internal auraDepositorAddress; - address internal auraRewardStakerAddress; - uint256 internal auraDepositorPTokenId; address internal pTokenAddress; bytes32 internal balancerPoolId; - // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) + // Full list of all assets as they are present in the Balancer pool + address[] internal poolAssetsMapped; + // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) - TODO better name also considered with deposits uint256 public maxWithdrawalSlippage; int256[50] private __reserved; @@ -36,56 +44,6 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256 _newMaxSlippagePercentage ); - struct InitConfig { - address platformAddress; // platformAddress Address of the Balancer's pool - address vaultAddress; // vaultAddress Address of the vault - address auraDepositorAddress; // auraDepositorAddress Address of the Auraa depositor(AKA booster) for this pool - address auraRewardStakerAddress; // auraRewardStakerAddress Address of the Aura rewards staker - uint256 auraDepositorPTokenId; // auraDepositorPTokenId Address of the Aura rewards staker - bytes32 balancerPoolId; // balancerPoolId bytes32 poolId - } - - /** - * Initializer for setting up strategy internal state. This overrides the - * InitializableAbstractStrategy initializer as Balancer's strategies don't fit - * well within that abstraction. - * @param _rewardTokenAddresses Address of BAL & AURA - * @param _assets Addresses of supported assets. MUST be passed in the same - * order as returned by coins on the pool contract, i.e. - * WETH, stETH - * @param _pTokens Platform Token corresponding addresses - * @param initConfig additional configuration - */ - function initialize( - address[] calldata _rewardTokenAddresses, // BAL & AURA - address[] calldata _assets, - address[] calldata _pTokens, - InitConfig calldata initConfig - ) external onlyGovernor initializer { - auraDepositorAddress = initConfig.auraDepositorAddress; - auraRewardStakerAddress = initConfig.auraRewardStakerAddress; - auraDepositorPTokenId = initConfig.auraDepositorPTokenId; - pTokenAddress = _pTokens[0]; - maxWithdrawalSlippage = 1e15; - balancerPoolId = initConfig.balancerPoolId; - IERC20[] memory poolAssets = getPoolAssets(); - uint256 assetsLength = _assets.length; - require (poolAssets.length == assetsLength, "Pool assets and _assets should be the same length."); - for (uint256 i = 0; i < assetsLength; ++i) { - (address strategyAsset, ) = fromPoolAsset(address(poolAssets[i]), 0); - require(_assets[i] == strategyAsset, "Pool assets and _assets should all have the same numerical order."); - } - - super._initialize( - initConfig.platformAddress, - initConfig.vaultAddress, - _rewardTokenAddresses, - _assets, - _pTokens - ); - _approveBase(); - } - /** * @dev Returns bool indicating whether asset is supported by strategy * @param _asset Address of the asset @@ -102,82 +60,122 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { function checkBalance(address _asset) external view + virtual override returns (uint256) { - (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock) = balancerVault.getPoolTokens(balancerPoolId); - // TODO: override in AURA implementation - uint256 yourPoolShare = IERC20(pTokenAddress).balanceOf(address(this)) / IERC20(pTokenAddress).totalSupply(); - + ( + IERC20[] memory tokens, + uint256[] memory balances, + uint256 lastChangeBlock + ) = balancerVault.getPoolTokens(balancerPoolId); + // yourPoolShare denominated in 1e18. (1e18 == 100%) + uint256 yourPoolShare = IERC20(pTokenAddress) + .balanceOf(address(this)) + .divPrecisely(IERC20(pTokenAddress).totalSupply()); + uint256 balancesLength = balances.length; - for (uint256 i=0; i < balances.length; ++i){ - if(address(tokens[i]) == _asset) { - return balances[i] * yourPoolShare; + for (uint256 i = 0; i < balances.length; ++i) { + (address poolAsset, ) = toPoolAsset(_asset, 0); + + if (address(tokens[i]) == poolAsset) { + return balances[i].mulTruncate(yourPoolShare); } } } - - - function getMinBPTExpected(address _asset, uint256 _amount) - internal - view - virtual - returns (uint256 minBptAmount) - { + function getMinBPTExpected( + address _asset, + uint256 _amount, + address _poolAsset, + uint256 _poolAmount + ) internal view virtual returns (uint256 minBptAmount) { + /* minBPT price is calculated by dividing the pool (sometimes wrapped) market price by the + * rateProviderRate of that asset: + * + * minBptPrice = pool_a_oracle_price / pool_a_rate + * + * Since we only have oracle prices for the unwrapped version of the assets the equation + * turns into: + * + * minBptPrice = from_pool_token(asset_oracle_price) / pool_a_rate + * + */ + console.log("getMinBPTExpected function"); + console.log("_poolAsset"); + console.log(_poolAsset); + uint256 rateProviderRate = getRateProviderRate(_poolAsset); address priceProvider = IVault(vaultAddress).priceProvider(); uint256 marketPrice = IOracle(priceProvider).price(_asset); - uint256 rateProviderRate = getRateProviderRate(_asset); - // TODO: account for some slippage? - return marketPrice.divPrecisely(rateProviderRate); + console.log("market price"); + console.log(marketPrice); // 1000000000000000000 + console.log("rate provider price"); + console.log(rateProviderRate); // 1000000000000000000 + (, uint256 assetAmount) = fromPoolAsset(_poolAsset, 1e18); + console.log("fromPoolAsset assetAmount"); + console.log(assetAmount); + uint256 minBPTnoSlippage = assetAmount + .mulTruncate(marketPrice) + .divPrecisely(rateProviderRate) + .mulTruncate(_amount); + console.log("minBPTnoSlippage"); + console.log(minBPTnoSlippage); + minBptAmount = + minBPTnoSlippage - + minBPTnoSlippage.mulTruncate(maxWithdrawalSlippage); + console.log("minBptAmount with slippage"); + console.log(minBptAmount); } - function getRateProviderRate(address _asset) internal virtual view returns(uint256); - - function _lpDepositAll() internal virtual - { + function getRateProviderRate(address _asset) + internal + view + virtual + returns (uint256); - } + function _lpDepositAll() internal virtual {} - function _lpWithdrawAll() internal virtual - { - - } + function _lpWithdrawAll() internal virtual {} /** - * Balancer returns assets and rateProviders for corresponding assets ordered + * Balancer returns assets and rateProviders for corresponding assets ordered * by numerical order. */ - function getPoolAssets() - internal - view - returns(IERC20[] memory assets) - { - (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock) = balancerVault.getPoolTokens(balancerPoolId); + function getPoolAssets() internal view returns (IERC20[] memory assets) { + ( + IERC20[] memory tokens, + uint256[] memory balances, + uint256 lastChangeBlock + ) = balancerVault.getPoolTokens(balancerPoolId); return tokens; } /** * Balancer pools might have wrapped versions of assets that the strategy - * is handling. This function takes care of the conversion: + * is handling. This function takes care of the conversion: * strategy asset -> pool asset */ function toPoolAsset(address asset, uint256 amount) - view internal - returns(address poolAsset, uint256 poolAmount) + view + returns (address poolAsset, uint256 poolAmount) { + poolAmount = 0; // if stEth - if (asset == 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84) { + if (asset == stEth) { // wstEth - poolAsset = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; - poolAmount = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0).getWstETHByStETH(amount); - // if frxEth - } else if (asset == 0x5E8422345238F34275888049021821E8E08CAa1f) { + poolAsset = wstEth; + if (amount > 0) { + poolAmount = IWstETH(wstEth).getWstETHByStETH(amount); + } + // if frxEth + } else if (asset == frxEth) { // sfrxEth - poolAsset = 0xac3E018457B222d93114458476f3E3416Abbe38F; - poolAmount = IERC4626(0xac3E018457B222d93114458476f3E3416Abbe38F).convertToShares(amount); + poolAsset = sfrxEth; + if (amount > 0) { + poolAmount = IERC4626(sfrxEth).convertToShares(amount); + } } else { poolAsset = asset; poolAmount = amount; @@ -186,14 +184,14 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { function wrapPoolAsset(address asset, uint256 amount) internal - returns(uint256 wrappedAmount) + returns (uint256 wrappedAmount) { // if stEth - if (asset == 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84) { - wrappedAmount = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0).wrap(amount); - // if frxEth - } else if (asset == 0x5E8422345238F34275888049021821E8E08CAa1f) { - wrappedAmount = IERC4626(0xac3E018457B222d93114458476f3E3416Abbe38F).deposit(amount, address(this)); + if (asset == stEth) { + wrappedAmount = IWstETH(wstEth).wrap(amount); + // if frxEth + } else if (asset == frxEth) { + wrappedAmount = IERC4626(sfrxEth).deposit(amount, address(this)); } else { wrappedAmount = amount; } @@ -201,37 +199,46 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { function unwrapPoolAsset(address asset, uint256 amount) internal - returns(uint256 wrappedAmount) + returns (uint256 wrappedAmount) { // if stEth - if (asset == 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84) { - wrappedAmount = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0).unwrap(amount); - // if frxEth - } else if (asset == 0x5E8422345238F34275888049021821E8E08CAa1f) { - wrappedAmount = IERC4626(0xac3E018457B222d93114458476f3E3416Abbe38F).withdraw(amount, address(this), address(this)); + if (asset == stEth) { + wrappedAmount = IWstETH(wstEth).unwrap(amount); + // if frxEth + } else if (asset == frxEth) { + wrappedAmount = IERC4626(sfrxEth).withdraw( + amount, + address(this), + address(this) + ); } else { wrappedAmount = amount; } } - function fromPoolAsset(address asset, uint256 amount) - view + function fromPoolAsset(address poolAsset, uint256 poolAmount) internal - returns(address strategyAsset, uint256 strategyAmount) + view + returns (address asset, uint256 amount) { + amount = 0; // if wstEth - if (asset == 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0) { + if (poolAsset == wstEth) { // stEth - strategyAsset = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; - strategyAmount = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0).getStETHByWstETH(amount); - // if frxEth - } else if (asset == 0xac3E018457B222d93114458476f3E3416Abbe38F) { + asset = stEth; + if (poolAmount > 0) { + amount = IWstETH(wstEth).getStETHByWstETH(poolAmount); + } + // if frxEth + } else if (poolAsset == sfrxEth) { // sfrxEth - strategyAsset = 0x5E8422345238F34275888049021821E8E08CAa1f; - strategyAmount = IERC4626(0xac3E018457B222d93114458476f3E3416Abbe38F).convertToAssets(amount); + asset = frxEth; + if (poolAmount > 0) { + amount = IERC4626(sfrxEth).convertToAssets(poolAmount); + } } else { - strategyAsset = asset; - strategyAmount = amount; + asset = poolAsset; + amount = poolAmount; } } @@ -260,15 +267,10 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { maxWithdrawalSlippage = _maxWithdrawalSlippage; } - function _approveBase() internal { + function _approveBase() internal virtual { IERC20 pToken = IERC20(pTokenAddress); // Balancer vault for BPT token (required for removing liquidity) pToken.safeApprove(address(balancerVault), 0); pToken.safeApprove(address(balancerVault), type(uint256).max); - - // Gauge for LP token - pToken.safeApprove(auraDepositorAddress, 0); - pToken.safeApprove(auraDepositorAddress, type(uint256).max); } - -} \ No newline at end of file +} diff --git a/contracts/deploy/071_balancer_wstETH_WETH.js b/contracts/deploy/071_balancer_wstETH_WETH.js index 402c3dc9d0..609c0b87eb 100644 --- a/contracts/deploy/071_balancer_wstETH_WETH.js +++ b/contracts/deploy/071_balancer_wstETH_WETH.js @@ -7,6 +7,7 @@ module.exports = deploymentWithGovernanceProposal( { deployName: "071_balancer_wstETH_WETH", forceDeploy: false, + //forceSkip: true, deployerIsProposer: true, //proposalId: , }, @@ -26,7 +27,10 @@ module.exports = deploymentWithGovernanceProposal( "OETHVaultAdmin", cOETHVaultProxy.address ); - const cOETHVault = await ethers.getContractAt("OETHVault", cOETHVaultProxy.address); + const cOETHVault = await ethers.getContractAt( + "OETHVault", + cOETHVaultProxy.address + ); // Deployer Actions // ---------------- @@ -59,22 +63,22 @@ module.exports = deploymentWithGovernanceProposal( // 3. Encode the init data const initFunction = "initialize(address[],address[],address[],(address,address,address,address,uint256,bytes32))"; - const initData = cOETHBalancerMetaPoolStrategy.interface.encodeFunctionData(initFunction, [ - [addresses.mainnet.BAL, addresses.mainnet.AURA], - [addresses.mainnet.stETH, addresses.mainnet.WETH], + const initData = cOETHBalancerMetaPoolStrategy.interface.encodeFunctionData( + initFunction, [ - addresses.mainnet.wstETH_WETH_BPT, - addresses.mainnet.wstETH_WETH_BPT - ], - [ - addresses.mainnet.wstETH_WETH_BPT, - cOETHVaultProxy.address, - addresses.mainnet.aureDepositor, // auraDepositorAddress, - addresses.mainnet.CurveOUSDMetaPool, // auraRewardStakerAddress - balancerWstEthWethPID, // auraDepositorPTokenId - "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080" + [addresses.mainnet.BAL, addresses.mainnet.AURA], + [addresses.mainnet.stETH, addresses.mainnet.WETH], + [addresses.mainnet.wstETH_WETH_BPT, addresses.mainnet.wstETH_WETH_BPT], + [ + addresses.mainnet.wstETH_WETH_BPT, + cOETHVaultProxy.address, + addresses.mainnet.auraRewardPool, + addresses.mainnet.CurveOUSDMetaPool, // auraRewardStakerAddress + balancerWstEthWethPID, // auraDepositorPTokenId + "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080", + ], ] - ]); + ); // 4. Init the proxy to point at the implementation await withConfirmation( diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index c513027055..9da3fda691 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -8,60 +8,78 @@ const { advanceBlocks, advanceTime, } = require("../helpers"); +const { BigNumber } = require("ethers"); const { balancerWstEthWethFixture, impersonateAndFundContract, } = require("../_fixture"); -forkOnlyDescribe("ForkTest: Balancer MetaStablePool stWeth/WETH Strategy", function () { - this.timeout(0); - // due to hardhat forked mode timeouts - retry failed tests up to 3 times - this.retries(3); +forkOnlyDescribe( + "ForkTest: Balancer MetaStablePool stWeth/WETH Strategy", + function () { + this.timeout(0); + // due to hardhat forked mode timeouts - retry failed tests up to 3 times + // this.retries(3); - let fixture; - beforeEach(async () => { - fixture = await loadFixture(balancerWstEthWethFixture); - }); - - describe.only("Mint", function () { - it("Should deploy WETH in Balancer MetaStablePool strategy", async function () { - const { josh, weth } = fixture; - await mintTest(fixture, josh, weth, "30"); + let fixture; + beforeEach(async () => { + fixture = await loadFixture(balancerWstEthWethFixture); }); - it("Should deploy stETH in Balancer MetaStablePool strategy", async function () { - const { josh, stETH } = fixture; - await mintTest(fixture, josh, stETH, "30"); + describe.only("Mint", function () { + it.only("Should deploy WETH in Balancer MetaStablePool strategy", async function () { + const { josh, weth, stETH } = fixture; + await mintTest(fixture, josh, weth, "30", [weth, stETH]); + }); + + it("Should deploy stETH in Balancer MetaStablePool strategy", async function () { + const { josh, stETH, weth } = fixture; + await mintTest(fixture, josh, stETH, "30", [weth, stETH]); + }); }); - }); - // set it as a last test that executes because we advance time and theat - // messes with recency of oracle prices - describe("Supply Revenue", function () { + // set it as a last test that executes because we advance time and theat + // messes with recency of oracle prices + describe("Supply Revenue", function () {}); + } +); + +async function getPoolBalance(strategy, allAssets) { + let currentBalancerBalance = BigNumber.from(0); + + for (const asset of allAssets) { + currentBalancerBalance = currentBalancerBalance.add( + await strategy.checkBalance(asset.address) + ); + } - }); -}); + return currentBalancerBalance; +} -async function mintTest(fixture, user, asset, amount = "30000") { +async function mintTest(fixture, user, asset, amount, allAssets) { const { oethVault, oeth, balancerWstEthWethStrategy } = fixture; await oethVault.connect(user).allocate(); - const unitAmount = await units(amount, asset); const currentSupply = await oeth.totalSupply(); const currentBalance = await oeth.connect(user).balanceOf(user.address); - const currentBalancerBalance = await balancerWstEthWethStrategy.checkBalance( - asset.address + const currentBalancerBalance = await getPoolBalance( + balancerWstEthWethStrategy, + allAssets ); // Mint OETH w/ asset + await asset.connect(user).approve(oethVault.address, unitAmount); await oethVault.connect(user).mint(asset.address, unitAmount, 0); await oethVault.connect(user).allocate(); const newBalance = await oeth.connect(user).balanceOf(user.address); const newSupply = await oeth.totalSupply(); - const newBalancerBalance = await balancerWstEthWethStrategy.checkBalance(asset.address); + const newBalancerBalance = await getPoolBalance( + balancerWstEthWethStrategy, + allAssets + ); const balanceDiff = newBalance.sub(currentBalance); // Ensure user has correct balance (w/ 1% slippage tolerance) @@ -81,4 +99,3 @@ async function mintTest(fixture, user, asset, amount = "30000") { 1 ); } - diff --git a/contracts/utils/addresses.js b/contracts/utils/addresses.js index 26a0301be3..02c333fd0b 100644 --- a/contracts/utils/addresses.js +++ b/contracts/utils/addresses.js @@ -171,8 +171,9 @@ addresses.mainnet.FraxETHStrategy = addresses.mainnet.BAL = "0xba100000625a3754423978a60c9317c58a424e3D"; addresses.mainnet.AURA = "0xc0c293ce456ff0ed870add98a0828dd4d2903dbf"; addresses.mainnet.wstETH = "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0"; -addresses.mainnet.wstETH_WETH_BPT = "0x32296969ef14eb0c6d29669c550d4a0449130230"; -addresses.mainnet.aureDepositor = "0x59d66c58e83a26d6a0e35114323f65c3945c89c1"; +addresses.mainnet.wstETH_WETH_BPT = + "0x32296969ef14eb0c6d29669c550d4a0449130230"; +addresses.mainnet.auraRewardPool = "0x59d66c58e83a26d6a0e35114323f65c3945c89c1"; // Tokens addresses.mainnet.sfrxETH = "0xac3E018457B222d93114458476f3E3416Abbe38F"; diff --git a/contracts/utils/constants.js b/contracts/utils/constants.js index 787d97751e..ec63f046f9 100644 --- a/contracts/utils/constants.js +++ b/contracts/utils/constants.js @@ -14,7 +14,7 @@ module.exports = { lusdMetapoolLPCRVPid, oethPoolLpPID, MAX_UINT256, - balancerWstEthWethPID + balancerWstEthWethPID, }; // These are all the metapool ids. For easier future reference From 10b6fdc31671edc9d9238a009bac78d30f5807ae Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Fri, 21 Jul 2023 15:22:33 +0200 Subject: [PATCH 13/67] add basic withdrawal / deposit functionality --- .../balancer/BalancerMetaPoolStrategy.sol | 158 +++++++++++++++--- .../strategies/balancer/BaseAuraStrategy.sol | 66 ++++++-- .../balancer/BaseBalancerStrategy.sol | 27 +-- .../balancerMetaStablePool.fork-test.js | 60 ++++++- 4 files changed, 242 insertions(+), 69 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index a58c90e1a8..1e7e33db7f 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -10,11 +10,14 @@ import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { IMetaStablePool } from "../../interfaces/balancer/IMetaStablePool.sol"; import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; +import { StableMath } from "../../utils/StableMath.sol"; import "hardhat/console.sol"; contract BalancerMetaPoolStrategy is BaseAuraStrategy { using SafeERC20 for IERC20; + using StableMath for uint256; + address internal immutable stETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; address internal immutable wstETH = @@ -49,14 +52,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { require(false, "Can not find rateProvider"); } - function withdraw( - address _recipient, - address _asset, - uint256 _amount - ) external override onlyVault nonReentrant {} - - function withdrawAll() external override onlyVaultOrGovernor nonReentrant {} - function deposit(address _asset, uint256 _amount) external override @@ -86,6 +81,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { return; } + emit Deposit(_asset, pTokenAddress, _amount); + (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( @@ -105,23 +102,14 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { wrapPoolAsset(_asset, _amount); - // console.log("xxx"); - // console.log(uint256(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT)); // 2 - // console.log(_amount); // 36523558823496626525 - // console.log(_asset); // 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 - // console.log("Max amounts in"); - // console.log(maxAmountsIn[0]); // 0 - // console.log(maxAmountsIn[1]); // 36523558823496626525 - + uint256 minBPT = getMinBPTExpected(_asset, _amount, poolAsset); // TODO: figure out why the slippage is so high - uint256 minBPT = getMinBPTExpected( - _asset, - _amount, - poolAsset, - poolAmount + uint256 minBPTwSlippage = minBPT.mulTruncate( + 1e18 - maxWithdrawalSlippage ); + // console.log("Min BPT expected"); - // console.log(minBPT); + // console.log(minBPTwSlippage); /* TOKEN_IN_FOR_EXACT_BPT_OUT: * User sends an estimated but unknown (computed at run time) quantity of a single token, @@ -132,14 +120,13 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ bytes memory userData = abi.encode( IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, - minBPT, + minBPTwSlippage, assetIndex ); - //bytes memory userData = abi.encode(IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, 0, assetIndex); IBalancerVault.JoinPoolRequest memory request = IBalancerVault .JoinPoolRequest(poolAssetsMapped, maxAmountsIn, userData, false); - console.log(IERC20(platformAddress).balanceOf(address(this))); + balancerVault.joinPool( balancerPoolId, address(this), @@ -150,6 +137,127 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { _lpDepositAll(); } + function withdraw( + address _recipient, + address _asset, + uint256 _amount + ) external override onlyVault nonReentrant { + (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); + + uint256 BPTtoWithdraw = getMinBPTExpected(_asset, _amount, poolAsset); + // adjust for slippage + // TODO: why slippage so high + BPTtoWithdraw = BPTtoWithdraw.mulTruncate(1e18 + maxWithdrawalSlippage); + + _lpWithdraw(BPTtoWithdraw); + + // TODO refactor this bit + (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( + balancerPoolId + ); + uint256 tokensLength = tokens.length; + uint256[] memory minAmountsOut = new uint256[](tokensLength); + uint256 assetIndex = 0; + for (uint256 i = 0; i < tokensLength; ++i) { + if (address(tokens[i]) == poolAsset) { + minAmountsOut[i] = poolAmount; + assetIndex = i; + } else { + minAmountsOut[i] = 0; + } + } + + /* Single asset exit: EXACT_BPT_IN_FOR_ONE_TOKEN_OUT: + * User sends a precise quantity of BPT, and receives an estimated but unknown + * (computed at run time) quantity of a single token + * + * ['uint256', 'uint256', 'uint256'] + * [EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, bptAmountIn, exitTokenIndex] + */ + bytes memory userData = abi.encode( + IBalancerVault.WeightedPoolExitKind.EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, + BPTtoWithdraw, + assetIndex + ); + + IBalancerVault.ExitPoolRequest memory request = IBalancerVault + .ExitPoolRequest(poolAssetsMapped, minAmountsOut, userData, false); + + balancerVault.exitPool( + balancerPoolId, + address(this), + // TODO: this is incorrect and should be altered when/if we intend to support + // pools that deal with native ETH + payable(address(this)), + request + ); + + unwrapPoolAsset(_asset, poolAmount); + IERC20(_asset).safeTransfer(_recipient, _amount); + } + + function withdrawAll() external override onlyVaultOrGovernor nonReentrant { + _lpWithdrawAll(); + + uint256 BPTtoWithdraw = IERC20(platformAddress).balanceOf( + address(this) + ); + + // TODO refactor this bit + (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault + .getPoolTokens(balancerPoolId); + + uint256 yourPoolShare = BPTtoWithdraw.divPrecisely( + IERC20(pTokenAddress).totalSupply() + ); + + uint256 assetsMappedLength = balances.length; + uint256[] memory minAmountsOut = new uint256[](assetsMappedLength); + for (uint256 i = 0; i < assetsMappedLength; ++i) { + (address poolAsset, ) = toPoolAsset(assetsMapped[i], 0); + + if (address(tokens[i]) == poolAsset) { + minAmountsOut[i] = balances[i] + .mulTruncate(yourPoolShare) + .mulTruncate(1e18 - maxWithdrawalSlippage); + } + } + + /* Proportional exit: EXACT_BPT_IN_FOR_TOKENS_OUT: + * User sends a precise quantity of BPT, and receives an estimated but unknown + * (computed at run time) quantity of a single token + * + * ['uint256', 'uint256'] + * [EXACT_BPT_IN_FOR_TOKENS_OUT, bptAmountIn] + */ + bytes memory userData = abi.encode( + IBalancerVault.WeightedPoolExitKind.EXACT_BPT_IN_FOR_TOKENS_OUT, + BPTtoWithdraw + ); + + IBalancerVault.ExitPoolRequest memory request = IBalancerVault + .ExitPoolRequest(poolAssetsMapped, minAmountsOut, userData, false); + + balancerVault.exitPool( + balancerPoolId, + address(this), + // TODO: this is incorrect and should be altered when/if we intend to support + // pools that deal with native ETH + payable(address(this)), + request + ); + + for (uint256 i = 0; i < assetsMappedLength; ++i) { + address asset = assetsMapped[i]; + (address poolAsset, ) = toPoolAsset(assetsMapped[i], 0); + unwrapPoolAsset(asset, IERC20(poolAsset).balanceOf(address(this))); + + uint256 transferAmount = IERC20(asset).balanceOf(address(this)); + IERC20(asset).safeTransfer(vaultAddress, transferAmount); + emit Withdrawal(asset, pTokenAddress, transferAmount); + } + } + function safeApproveAllTokens() external override diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 66192acf41..454643bc5c 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -8,12 +8,14 @@ pragma solidity ^0.8.0; import { BaseBalancerStrategy } from "./BaseBalancerStrategy.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; -import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol";" +import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; +import { StableMath } from "../../utils/StableMath.sol"; import "hardhat/console.sol"; abstract contract BaseAuraStrategy is BaseBalancerStrategy { using SafeERC20 for IERC20; + using StableMath for uint256; address internal auraRewardPoolAddress; address internal auraRewardStakerAddress; @@ -54,10 +56,16 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { balancerPoolId = initConfig.balancerPoolId; IERC20[] memory poolAssets = getPoolAssets(); uint256 assetsLength = _assets.length; - require (poolAssets.length == assetsLength, "Pool assets and _assets should be the same length."); + require( + poolAssets.length == assetsLength, + "Pool assets and _assets should be the same length." + ); for (uint256 i = 0; i < assetsLength; ++i) { (address asset, ) = fromPoolAsset(address(poolAssets[i]), 0); - require(_assets[i] == asset, "Pool assets and _assets should all have the same numerical order."); + require( + _assets[i] == asset, + "Pool assets and _assets should all have the same numerical order." + ); // TODO: double check if this fits in here poolAssetsMapped.push(address(poolAssets[i])); } @@ -72,33 +80,55 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { _approveBase(); } - function _lpDepositAll() internal virtual override - { + function _lpDepositAll() internal virtual override { uint256 bptBalance = IERC20(platformAddress).balanceOf(address(this)); - IERC4626(auraRewardPoolAddress).deposit(bptBalance); + IERC4626(auraRewardPoolAddress).deposit(bptBalance, address(this)); } - function _lpWithdrawAll() internal virtual override - { - + function _lpWithdraw(uint256 numBPTTokens) internal virtual override { + IERC4626(auraRewardPoolAddress).withdraw( + numBPTTokens, + address(this), + address(this) + ); + } + + function _lpWithdrawAll() internal virtual override { + uint256 bptBalance = IERC4626(auraRewardPoolAddress).balanceOf( + address(this) + ); + IERC4626(auraRewardPoolAddress).withdraw( + bptBalance, + address(this), + address(this) + ); } function checkBalance(address _asset) external view - override virtual + override returns (uint256) { - (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock) = balancerVault.getPoolTokens(balancerPoolId); - uint256 bptBalance = IERC20(pTokenAddress).balanceOf(address(this)) + IERC4626(auraRewardPoolAddress).balanceOf(address(this)); + ( + IERC20[] memory tokens, + uint256[] memory balances, + uint256 lastChangeBlock + ) = balancerVault.getPoolTokens(balancerPoolId); + // pool balance + aura balance + uint256 bptBalance = IERC20(pTokenAddress).balanceOf(address(this)) + + IERC4626(auraRewardPoolAddress).balanceOf(address(this)); + // yourPoolShare denominated in 1e18. (1e18 == 100%) - uint256 yourPoolShare = IERC20(pTokenAddress).balanceOf(address(this)).divPrecisely(IERC20(pTokenAddress).totalSupply()); - + uint256 yourPoolShare = bptBalance.divPrecisely( + IERC20(pTokenAddress).totalSupply() + ); + uint256 balancesLength = balances.length; - for (uint256 i=0; i < balances.length; ++i){ - (address poolAsset,) = toPoolAsset(_asset, 0); - if(address(tokens[i]) == poolAsset) { + for (uint256 i = 0; i < balances.length; ++i) { + (address poolAsset, ) = toPoolAsset(_asset, 0); + if (address(tokens[i]) == poolAsset) { return balances[i].mulTruncate(yourPoolShare); } } @@ -112,4 +142,4 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { pToken.safeApprove(auraRewardPoolAddress, 0); pToken.safeApprove(auraRewardPoolAddress, type(uint256).max); } -} \ No newline at end of file +} diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index dcc9d41229..2afc0ee2a1 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -87,8 +87,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { function getMinBPTExpected( address _asset, uint256 _amount, - address _poolAsset, - uint256 _poolAmount + address _poolAsset ) internal view virtual returns (uint256 minBptAmount) { /* minBPT price is calculated by dividing the pool (sometimes wrapped) market price by the * rateProviderRate of that asset: @@ -101,31 +100,15 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * minBptPrice = from_pool_token(asset_oracle_price) / pool_a_rate * */ - console.log("getMinBPTExpected function"); - console.log("_poolAsset"); - console.log(_poolAsset); uint256 rateProviderRate = getRateProviderRate(_poolAsset); address priceProvider = IVault(vaultAddress).priceProvider(); uint256 marketPrice = IOracle(priceProvider).price(_asset); - console.log("market price"); - console.log(marketPrice); // 1000000000000000000 - console.log("rate provider price"); - console.log(rateProviderRate); // 1000000000000000000 (, uint256 assetAmount) = fromPoolAsset(_poolAsset, 1e18); - console.log("fromPoolAsset assetAmount"); - console.log(assetAmount); - uint256 minBPTnoSlippage = assetAmount + minBptAmount = assetAmount .mulTruncate(marketPrice) .divPrecisely(rateProviderRate) .mulTruncate(_amount); - console.log("minBPTnoSlippage"); - console.log(minBPTnoSlippage); - minBptAmount = - minBPTnoSlippage - - minBPTnoSlippage.mulTruncate(maxWithdrawalSlippage); - console.log("minBptAmount with slippage"); - console.log(minBptAmount); } function getRateProviderRate(address _asset) @@ -134,9 +117,11 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { virtual returns (uint256); - function _lpDepositAll() internal virtual {} + function _lpDepositAll() internal virtual; - function _lpWithdrawAll() internal virtual {} + function _lpWithdraw(uint256 numBPTTokens) internal virtual; + + function _lpWithdrawAll() internal virtual; /** * Balancer returns assets and rateProviders for corresponding assets ordered diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 9da3fda691..9b4a97ab2c 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -27,7 +27,7 @@ forkOnlyDescribe( }); describe.only("Mint", function () { - it.only("Should deploy WETH in Balancer MetaStablePool strategy", async function () { + it("Should deploy WETH in Balancer MetaStablePool strategy", async function () { const { josh, weth, stETH } = fixture; await mintTest(fixture, josh, weth, "30", [weth, stETH]); }); @@ -38,9 +38,59 @@ forkOnlyDescribe( }); }); - // set it as a last test that executes because we advance time and theat - // messes with recency of oracle prices - describe("Supply Revenue", function () {}); + describe.only("Withdraw", function () { + it("Should be able to withdraw some amount of pool liquidity", async function () { + const { josh, weth, stETH, balancerWstEthWethStrategy, oethVault } = + fixture; + await mintTest(fixture, josh, weth, "30", [weth, stETH]); + + const wethBalanceBeforeVault = await weth.balanceOf(oethVault.address); + const wethToWithdraw = await units("10", weth); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + await balancerWstEthWethStrategy + .connect(oethVaultSigner) + .withdraw(oethVault.address, weth.address, wethToWithdraw); + + const wethBalanceDiffVault = ( + await weth.balanceOf(oethVault.address) + ).sub(wethBalanceBeforeVault); + expect(wethBalanceDiffVault).to.approxEqualTolerance(wethToWithdraw, 1); + }); + + it("Should be able to withdraw all of pool liquidity", async function () { + const { josh, weth, stETH, balancerWstEthWethStrategy, oethVault } = + fixture; + await mintTest(fixture, josh, weth, "30", [weth, stETH]); + + const wethBalanceBefore = await balancerWstEthWethStrategy.checkBalance( + weth.address + ); + const stEthBalanceBefore = + await balancerWstEthWethStrategy.checkBalance(stETH.address); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + await balancerWstEthWethStrategy.connect(oethVaultSigner).withdrawAll(); + + const wethBalanceDiff = wethBalanceBefore.sub( + await balancerWstEthWethStrategy.checkBalance(weth.address) + ); + const stEthBalanceDiff = stEthBalanceBefore.sub( + await balancerWstEthWethStrategy.checkBalance(stETH.address) + ); + + expect(wethBalanceDiff).to.be.gte(await units("15", weth), 1); + expect(stEthBalanceDiff).to.be.gte(await units("15", stETH), 1); + }); + }); + + describe("Harvest rewards", function () {}); } ); @@ -96,6 +146,6 @@ async function mintTest(fixture, user, asset, amount, allAssets) { // Should have liquidity in Morpho expect(balancerLiquidityDiff).to.approxEqualTolerance( await units(amount, asset), - 1 + 15 // TODO why such high slippage ); } From 807e8c44b3ef28707fc469b599e77e46a905bd43 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Fri, 21 Jul 2023 23:39:06 +0200 Subject: [PATCH 14/67] correct the BPT calculation --- .../interfaces/balancer/IRateProvider.sol | 1 - .../balancer/BalancerMetaPoolStrategy.sol | 9 +-- .../strategies/balancer/BaseAuraStrategy.sol | 26 ++++++--- .../balancer/BaseBalancerStrategy.sol | 57 +++++++++++++------ .../balancerMetaStablePool.fork-test.js | 10 +++- 5 files changed, 71 insertions(+), 32 deletions(-) diff --git a/contracts/contracts/interfaces/balancer/IRateProvider.sol b/contracts/contracts/interfaces/balancer/IRateProvider.sol index 29813706a9..ac16581e2d 100644 --- a/contracts/contracts/interfaces/balancer/IRateProvider.sol +++ b/contracts/contracts/interfaces/balancer/IRateProvider.sol @@ -14,7 +14,6 @@ pragma solidity ^0.8.0; -// TODO: pull this from the monorepo interface IRateProvider { function getRate() external view returns (uint256); } diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 1e7e33db7f..3e49b81377 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -102,15 +102,11 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { wrapPoolAsset(_asset, _amount); - uint256 minBPT = getMinBPTExpected(_asset, _amount, poolAsset); - // TODO: figure out why the slippage is so high + uint256 minBPT = getBPTExpected(_asset, _amount, poolAsset); uint256 minBPTwSlippage = minBPT.mulTruncate( 1e18 - maxWithdrawalSlippage ); - // console.log("Min BPT expected"); - // console.log(minBPTwSlippage); - /* TOKEN_IN_FOR_EXACT_BPT_OUT: * User sends an estimated but unknown (computed at run time) quantity of a single token, * and receives a precise quantity of BPT. @@ -144,9 +140,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { ) external override onlyVault nonReentrant { (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); - uint256 BPTtoWithdraw = getMinBPTExpected(_asset, _amount, poolAsset); + uint256 BPTtoWithdraw = getBPTExpected(_asset, _amount, poolAsset); // adjust for slippage - // TODO: why slippage so high BPTtoWithdraw = BPTtoWithdraw.mulTruncate(1e18 + maxWithdrawalSlippage); _lpWithdraw(BPTtoWithdraw); diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 454643bc5c..82901f188e 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -10,6 +10,7 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; import { StableMath } from "../../utils/StableMath.sol"; +import { IRewardStaking } from "../IRewardStaking.sol"; import "hardhat/console.sol"; @@ -52,7 +53,7 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { auraRewardStakerAddress = initConfig.auraRewardStakerAddress; auraDepositorPTokenId = initConfig.auraDepositorPTokenId; pTokenAddress = _pTokens[0]; - maxWithdrawalSlippage = 10e16; + maxWithdrawalSlippage = 1e15; balancerPoolId = initConfig.balancerPoolId; IERC20[] memory poolAssets = getPoolAssets(); uint256 assetsLength = _assets.length; @@ -86,10 +87,9 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { } function _lpWithdraw(uint256 numBPTTokens) internal virtual override { - IERC4626(auraRewardPoolAddress).withdraw( + IRewardStaking(auraRewardPoolAddress).withdrawAndUnwrap( numBPTTokens, - address(this), - address(this) + true // also claim reward tokens ); } @@ -97,13 +97,25 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { uint256 bptBalance = IERC4626(auraRewardPoolAddress).balanceOf( address(this) ); - IERC4626(auraRewardPoolAddress).withdraw( + + IRewardStaking(auraRewardPoolAddress).withdrawAndUnwrap( bptBalance, - address(this), - address(this) + true // also claim reward tokens ); } + function collectRewardTokens() + external + virtual + override + onlyHarvester + nonReentrant + { + // Collect CRV and CVX + IRewardStaking(auraRewardPoolAddress).getReward(); + _collectRewardTokens(); + } + function checkBalance(address _asset) external view diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 2afc0ee2a1..ed4fdc86a8 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -14,7 +14,6 @@ import { IVault } from "../../interfaces/IVault.sol"; import { IWstETH } from "../../interfaces/IWstETH.sol"; import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; import { StableMath } from "../../utils/StableMath.sol"; - import "hardhat/console.sol"; abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { @@ -69,46 +68,72 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256[] memory balances, uint256 lastChangeBlock ) = balancerVault.getPoolTokens(balancerPoolId); + // yourPoolShare denominated in 1e18. (1e18 == 100%) uint256 yourPoolShare = IERC20(pTokenAddress) .balanceOf(address(this)) .divPrecisely(IERC20(pTokenAddress).totalSupply()); uint256 balancesLength = balances.length; - for (uint256 i = 0; i < balances.length; ++i) { + for (uint256 i = 0; i < balancesLength; ++i) { (address poolAsset, ) = toPoolAsset(_asset, 0); if (address(tokens[i]) == poolAsset) { - return balances[i].mulTruncate(yourPoolShare); + (, uint256 assetAmount) = fromPoolAsset( + poolAsset, + balances[i].mulTruncate(yourPoolShare) + ); + return assetAmount; } } } - function getMinBPTExpected( + function getBPTExpected( address _asset, uint256 _amount, address _poolAsset - ) internal view virtual returns (uint256 minBptAmount) { - /* minBPT price is calculated by dividing the pool (sometimes wrapped) market price by the - * rateProviderRate of that asset: + ) internal view virtual returns (uint256 bptExpected) { + /* BPT price is calculated by dividing the pool (sometimes wrapped) market price by the + * rateProviderRate of that asset. To get BPT expected we need to multiply that by underlying + * asset amount divided by BPT token rate. BPT token rate is similar to Curve's virtual_price + * and expresses how much has the price of BPT appreciated in relation to the underlying assets. * - * minBptPrice = pool_a_oracle_price / pool_a_rate + * bptPrice = pool_a_oracle_price / pool_a_rate * * Since we only have oracle prices for the unwrapped version of the assets the equation * turns into: * - * minBptPrice = from_pool_token(asset_oracle_price) / pool_a_rate + * bptPrice = from_pool_token(asset_amount).amount * oracle_price / pool_a_rate + * + * bptExpected = bptPrice(in relation to specified asset) * asset_amount / BPT_token_rate * */ - uint256 rateProviderRate = getRateProviderRate(_poolAsset); + uint256 poolTokenRate = getRateProviderRate(_poolAsset); address priceProvider = IVault(vaultAddress).priceProvider(); - uint256 marketPrice = IOracle(priceProvider).price(_asset); + uint256 strategyAssetMarketPrice = IOracle(priceProvider).price(_asset); + uint256 bptRate = IRateProvider(platformAddress).getRate(); + + (, uint256 strategyAssetPerPoolToken) = fromPoolAsset(_poolAsset, 1e18); + bptExpected = strategyAssetPerPoolToken + .mulTruncate(_amount) + .mulTruncate(strategyAssetMarketPrice) + .divPrecisely(bptRate) + .divPrecisely(poolTokenRate); - (, uint256 assetAmount) = fromPoolAsset(_poolAsset, 1e18); - minBptAmount = assetAmount - .mulTruncate(marketPrice) - .divPrecisely(rateProviderRate) - .mulTruncate(_amount); + // console.log("getBPTExpected START"); + // console.log("_asset"); + // console.log(_asset); + // console.log("_amount"); + // console.log(_amount); + // console.log("poolTokenRate"); + // console.log(poolTokenRate); + // console.log("strategyAssetMarketPrice"); + // console.log(strategyAssetMarketPrice); + // console.log("bptExpected"); + // console.log(bptExpected); + // console.log("bptRate"); + // console.log(bptRate); + // console.log("getBPTExpected END"); } function getRateProviderRate(address _asset) diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 9b4a97ab2c..dce0a1bc34 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -90,7 +90,15 @@ forkOnlyDescribe( }); }); - describe("Harvest rewards", function () {}); + describe.only("Harvest rewards", function () { + it("Should be able to collect reward tokens", async function () { + const { josh, balancerWstEthWethStrategy, oethHarvester } = fixture; + + await oethHarvester + .connect(josh) + ["harvestAndSwap(address)"](balancerWstEthWethStrategy.address); + }); + }); } ); From 8f16b4ebdfed1077d35c3b7c748880208626b320 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Sun, 23 Jul 2023 13:41:57 +0200 Subject: [PATCH 15/67] prettier + lint --- .../balancer/BalancerMetaPoolStrategy.sol | 7 +++++ .../strategies/balancer/BaseAuraStrategy.sol | 12 +++---- .../balancer/BaseBalancerStrategy.sol | 15 +++------ contracts/test/_fixture.js | 31 ++++++------------- .../balancerMetaStablePool.fork-test.js | 15 +++------ 5 files changed, 32 insertions(+), 48 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 3e49b81377..4d2c0a1804 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -81,6 +81,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { return; } + //TODO: re-entrency protection + emit Deposit(_asset, pTokenAddress, _amount); (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); @@ -146,6 +148,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { _lpWithdraw(BPTtoWithdraw); + //TODO: re-entrency protection + // TODO refactor this bit (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( balancerPoolId @@ -198,6 +202,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address(this) ); + //TODO: re-entrency protection + // TODO refactor this bit (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault .getPoolTokens(balancerPoolId); @@ -265,6 +271,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { _approveBase(); } + // solhint-disable-next-line no-unused-vars function _abstractSetPToken(address _asset, address _pToken) internal override diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 82901f188e..b54bedcd05 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -21,7 +21,8 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { address internal auraRewardPoolAddress; address internal auraRewardStakerAddress; uint256 internal auraDepositorPTokenId; - int256[50] private __reserved; + // renamed from __reserved to not shadow BaseBalancerStrategy.__reserved, + int256[50] private __reserved_2; struct InitConfig { address platformAddress; // platformAddress Address of the Balancer's pool @@ -123,11 +124,8 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { override returns (uint256) { - ( - IERC20[] memory tokens, - uint256[] memory balances, - uint256 lastChangeBlock - ) = balancerVault.getPoolTokens(balancerPoolId); + (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault + .getPoolTokens(balancerPoolId); // pool balance + aura balance uint256 bptBalance = IERC20(pTokenAddress).balanceOf(address(this)) + IERC4626(auraRewardPoolAddress).balanceOf(address(this)); @@ -138,7 +136,7 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { ); uint256 balancesLength = balances.length; - for (uint256 i = 0; i < balances.length; ++i) { + for (uint256 i = 0; i < balancesLength; ++i) { (address poolAsset, ) = toPoolAsset(_asset, 0); if (address(tokens[i]) == poolAsset) { return balances[i].mulTruncate(yourPoolShare); diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index ed4fdc86a8..0883b9c619 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -63,11 +63,8 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { override returns (uint256) { - ( - IERC20[] memory tokens, - uint256[] memory balances, - uint256 lastChangeBlock - ) = balancerVault.getPoolTokens(balancerPoolId); + (IERC20[] memory tokens, uint256[] memory balances) = balancerVault + .getPoolTokens(balancerPoolId); // yourPoolShare denominated in 1e18. (1e18 == 100%) uint256 yourPoolShare = IERC20(pTokenAddress) @@ -153,11 +150,9 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * by numerical order. */ function getPoolAssets() internal view returns (IERC20[] memory assets) { - ( - IERC20[] memory tokens, - uint256[] memory balances, - uint256 lastChangeBlock - ) = balancerVault.getPoolTokens(balancerPoolId); + (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( + balancerPoolId + ); return tokens; } diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 8fab3f3209..283a527a80 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -833,32 +833,21 @@ async function convexVaultFixture() { */ async function balancerWstEthWethFixture() { const fixture = await loadFixture(defaultFixture); - const { oethVault, timelock, weth, balancerWstEthWethStrategy } = fixture; + const { oethVault, timelock, weth, stETH, balancerWstEthWethStrategy } = + fixture; - await fixture.oethVault + await oethVault .connect(timelock) - .setAssetDefaultStrategy( - fixture.weth.address, - fixture.balancerWstEthWethStrategy.address - ); - await fixture.oethVault + .setAssetDefaultStrategy(weth.address, balancerWstEthWethStrategy.address); + await oethVault .connect(timelock) - .setAssetDefaultStrategy( - fixture.stETH.address, - fixture.balancerWstEthWethStrategy.address - ); - await fixture.oethVault + .setAssetDefaultStrategy(stETH.address, balancerWstEthWethStrategy.address); + await oethVault .connect(timelock) - .setAssetDefaultStrategy( - fixture.weth.address, - fixture.balancerWstEthWethStrategy.address - ); - await fixture.oethVault + .setAssetDefaultStrategy(weth.address, balancerWstEthWethStrategy.address); + await oethVault .connect(timelock) - .setAssetDefaultStrategy( - fixture.stETH.address, - fixture.balancerWstEthWethStrategy.address - ); + .setAssetDefaultStrategy(stETH.address, balancerWstEthWethStrategy.address); return fixture; } diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index dce0a1bc34..e4e14dce46 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -1,13 +1,7 @@ const { expect } = require("chai"); const { loadFixture } = require("ethereum-waffle"); -const { - units, - ousdUnits, - forkOnlyDescribe, - advanceBlocks, - advanceTime, -} = require("../helpers"); +const { units, ousdUnits, forkOnlyDescribe } = require("../helpers"); const { BigNumber } = require("ethers"); const { balancerWstEthWethFixture, @@ -94,9 +88,10 @@ forkOnlyDescribe( it("Should be able to collect reward tokens", async function () { const { josh, balancerWstEthWethStrategy, oethHarvester } = fixture; - await oethHarvester - .connect(josh) - ["harvestAndSwap(address)"](balancerWstEthWethStrategy.address); + await oethHarvester.connect(josh)[ + // eslint-disable-next-line + "harvestAndSwap(address)" + ](balancerWstEthWethStrategy.address); }); }); } From 1c782a50e99c17f8f618247513903af67dd08c4b Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Sun, 23 Jul 2023 14:51:56 +0200 Subject: [PATCH 16/67] simplify the BPT price calculation --- .../balancer/BalancerMetaPoolStrategy.sol | 4 +- .../balancer/BaseBalancerStrategy.sol | 39 +++++++------------ 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 4d2c0a1804..e39f83adc1 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -104,7 +104,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { wrapPoolAsset(_asset, _amount); - uint256 minBPT = getBPTExpected(_asset, _amount, poolAsset); + uint256 minBPT = getBPTExpected(_asset, _amount); uint256 minBPTwSlippage = minBPT.mulTruncate( 1e18 - maxWithdrawalSlippage ); @@ -142,7 +142,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { ) external override onlyVault nonReentrant { (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); - uint256 BPTtoWithdraw = getBPTExpected(_asset, _amount, poolAsset); + uint256 BPTtoWithdraw = getBPTExpected(_asset, _amount); // adjust for slippage BPTtoWithdraw = BPTtoWithdraw.mulTruncate(1e18 + maxWithdrawalSlippage); diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 0883b9c619..918d963333 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -63,7 +63,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { override returns (uint256) { - (IERC20[] memory tokens, uint256[] memory balances) = balancerVault + (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault .getPoolTokens(balancerPoolId); // yourPoolShare denominated in 1e18. (1e18 == 100%) @@ -87,50 +87,37 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { function getBPTExpected( address _asset, - uint256 _amount, - address _poolAsset + uint256 _amount ) internal view virtual returns (uint256 bptExpected) { /* BPT price is calculated by dividing the pool (sometimes wrapped) market price by the * rateProviderRate of that asset. To get BPT expected we need to multiply that by underlying * asset amount divided by BPT token rate. BPT token rate is similar to Curve's virtual_price * and expresses how much has the price of BPT appreciated in relation to the underlying assets. * - * bptPrice = pool_a_oracle_price / pool_a_rate + * bptPrice = pool_asset_oracle_price / pool_asset_rate * * Since we only have oracle prices for the unwrapped version of the assets the equation * turns into: * - * bptPrice = from_pool_token(asset_amount).amount * oracle_price / pool_a_rate + * bptPrice = from_pool_token(asset_amount).amount * oracle_price / pool_asset_rate * * bptExpected = bptPrice(in relation to specified asset) * asset_amount / BPT_token_rate * + * and since from_pool_token(asset_amount).amount and pool_asset_rate cancel each-other out + * this makes the final equation: + * + * bptExpected = oracle_price * asset_amount / BPT_token_rate + * + * more explanation here: + * https://www.notion.so/originprotocol/Support-Balancer-OETH-strategy-9becdea132704e588782a919d7d471eb?pvs=4#382834f9815e46a7937f3acca0f637c5 */ - uint256 poolTokenRate = getRateProviderRate(_poolAsset); address priceProvider = IVault(vaultAddress).priceProvider(); uint256 strategyAssetMarketPrice = IOracle(priceProvider).price(_asset); uint256 bptRate = IRateProvider(platformAddress).getRate(); - (, uint256 strategyAssetPerPoolToken) = fromPoolAsset(_poolAsset, 1e18); - bptExpected = strategyAssetPerPoolToken - .mulTruncate(_amount) + bptExpected = _amount .mulTruncate(strategyAssetMarketPrice) - .divPrecisely(bptRate) - .divPrecisely(poolTokenRate); - - // console.log("getBPTExpected START"); - // console.log("_asset"); - // console.log(_asset); - // console.log("_amount"); - // console.log(_amount); - // console.log("poolTokenRate"); - // console.log(poolTokenRate); - // console.log("strategyAssetMarketPrice"); - // console.log(strategyAssetMarketPrice); - // console.log("bptExpected"); - // console.log(bptExpected); - // console.log("bptRate"); - // console.log(bptRate); - // console.log("getBPTExpected END"); + .divPrecisely(bptRate); } function getRateProviderRate(address _asset) From faa7eb52ff4207de84ed184ee7b97008d2b535f8 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Sun, 23 Jul 2023 15:16:30 +0200 Subject: [PATCH 17/67] add read-only re-entrancy protection --- .../interfaces/balancer/IBalancerVault.sol | 24 ++ .../balancer/BalancerMetaPoolStrategy.sol | 19 +- .../balancer/BaseBalancerStrategy.sol | 41 ++- .../balancer/VaultReentrancyLib.sol | 84 +++++ contracts/contracts/utils/BalancerErrors.sol | 305 ++++++++++++++++++ 5 files changed, 463 insertions(+), 10 deletions(-) create mode 100644 contracts/contracts/strategies/balancer/VaultReentrancyLib.sol create mode 100644 contracts/contracts/utils/BalancerErrors.sol diff --git a/contracts/contracts/interfaces/balancer/IBalancerVault.sol b/contracts/contracts/interfaces/balancer/IBalancerVault.sol index 499837a9a5..61e3a0dd8e 100644 --- a/contracts/contracts/interfaces/balancer/IBalancerVault.sol +++ b/contracts/contracts/interfaces/balancer/IBalancerVault.sol @@ -136,4 +136,28 @@ interface IBalancerVault { uint256[] memory balances, uint256 lastChangeBlock ); + + /** + * @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer) + * and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as + * it lets integrators reuse a user's Vault allowance. + * + * For each operation, if the caller is not `sender`, it must be an authorized relayer for them. + */ + function manageUserBalance(UserBalanceOp[] memory ops) external payable; + + struct UserBalanceOp { + UserBalanceOpKind kind; + address asset; + uint256 amount; + address sender; + address payable recipient; + } + + enum UserBalanceOpKind { + DEPOSIT_INTERNAL, + WITHDRAW_INTERNAL, + TRANSFER_INTERNAL, + TRANSFER_EXTERNAL + } } diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index e39f83adc1..c36fe95593 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -55,13 +55,20 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { function deposit(address _asset, uint256 _amount) external override + whenNotInVaultContext onlyVault nonReentrant { _deposit(_asset, _amount); } - function depositAll() external override onlyVault nonReentrant { + function depositAll() + external + override + whenNotInVaultContext + onlyVault + nonReentrant + { uint256 assetsLength = assetsMapped.length; for (uint256 i = 0; i < assetsLength; ++i) { uint256 balance = IERC20(assetsMapped[i]).balanceOf(address(this)); @@ -139,7 +146,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address _recipient, address _asset, uint256 _amount - ) external override onlyVault nonReentrant { + ) external override whenNotInVaultContext onlyVault nonReentrant { (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); uint256 BPTtoWithdraw = getBPTExpected(_asset, _amount); @@ -195,7 +202,13 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { IERC20(_asset).safeTransfer(_recipient, _amount); } - function withdrawAll() external override onlyVaultOrGovernor nonReentrant { + function withdrawAll() + external + override + whenNotInVaultContext + onlyVaultOrGovernor + nonReentrant + { _lpWithdrawAll(); uint256 BPTtoWithdraw = IERC20(platformAddress).balanceOf( diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 918d963333..ef4dc56ce0 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -9,6 +9,7 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s import { IERC20, InitializableAbstractStrategy } from "../../utils/InitializableAbstractStrategy.sol"; import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; +import { VaultReentrancyLib } from "./VaultReentrancyLib.sol"; import { IOracle } from "../../interfaces/IOracle.sol"; import { IVault } from "../../interfaces/IVault.sol"; import { IWstETH } from "../../interfaces/IWstETH.sol"; @@ -43,6 +44,19 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256 _newMaxSlippagePercentage ); + /** + * @dev Ensure we are not in a Vault context when this function is called, by attempting a no-op internal + * balance operation. If we are already in a Vault transaction (e.g., a swap, join, or exit), the Vault's + * reentrancy protection will cause this function to revert. + * + * Use this modifier with any function that can cause a state change in a pool and is either public itself, + * or called by a public function *outside* a Vault operation (e.g., join, exit, or swap). + */ + modifier whenNotInVaultContext() { + VaultReentrancyLib.ensureNotInVaultContext(balancerVault); + _; + } + /** * @dev Returns bool indicating whether asset is supported by strategy * @param _asset Address of the asset @@ -85,10 +99,12 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } } - function getBPTExpected( - address _asset, - uint256 _amount - ) internal view virtual returns (uint256 bptExpected) { + function getBPTExpected(address _asset, uint256 _amount) + internal + view + virtual + returns (uint256 bptExpected) + { /* BPT price is calculated by dividing the pool (sometimes wrapped) market price by the * rateProviderRate of that asset. To get BPT expected we need to multiply that by underlying * asset amount divided by BPT token rate. BPT token rate is similar to Curve's virtual_price @@ -144,9 +160,9 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } /** - * Balancer pools might have wrapped versions of assets that the strategy - * is handling. This function takes care of the conversion: - * strategy asset -> pool asset + * If an asset is rebasing the Balancer pools have a wrapped versions of assets + * that the strategy supports. This function converts the pool(wrapped) asset + * and corresponding amount to strategy asset. */ function toPoolAsset(address asset, uint256 amount) internal @@ -174,6 +190,9 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } } + /** + * Converts rebasing asset to its wrapped counterpart. + */ function wrapPoolAsset(address asset, uint256 amount) internal returns (uint256 wrappedAmount) @@ -189,6 +208,9 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } } + /** + * Converts wrapped asset to its rebasing counterpart. + */ function unwrapPoolAsset(address asset, uint256 amount) internal returns (uint256 wrappedAmount) @@ -208,6 +230,11 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } } + /** + * If an asset is rebasing the Balancer pools have a wrapped versions of assets + * that the strategy supports. This function converts the rebasing strategy asset + * and corresponding amount to wrapped(pool) asset. + */ function fromPoolAsset(address poolAsset, uint256 poolAmount) internal view diff --git a/contracts/contracts/strategies/balancer/VaultReentrancyLib.sol b/contracts/contracts/strategies/balancer/VaultReentrancyLib.sol new file mode 100644 index 0000000000..c579047cf8 --- /dev/null +++ b/contracts/contracts/strategies/balancer/VaultReentrancyLib.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pragma solidity >=0.7.0 <0.9.0; + +import "../../utils/BalancerErrors.sol"; +import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; + +library VaultReentrancyLib { + /** + * @dev Ensure we are not in a Vault context when this function is called, by attempting a no-op internal + * balance operation. If we are already in a Vault transaction (e.g., a swap, join, or exit), the Vault's + * reentrancy protection will cause this function to revert. + * + * The exact function call doesn't really matter: we're just trying to trigger the Vault reentrancy check + * (and not hurt anything in case it works). An empty operation array with no specific operation at all works + * for that purpose, and is also the least expensive in terms of gas and bytecode size. + * + * Call this at the top of any function that can cause a state change in a pool and is either public itself, + * or called by a public function *outside* a Vault operation (e.g., join, exit, or swap). + * + * If this is *not* called in functions that are vulnerable to the read-only reentrancy issue described + * here (https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345), those functions are unsafe, + * and subject to manipulation that may result in loss of funds. + */ + function ensureNotInVaultContext(IBalancerVault vault) internal view { + // Perform the following operation to trigger the Vault's reentrancy guard: + // + // IBalancerVault.UserBalanceOp[] memory noop = new IBalancerVault.UserBalanceOp[](0); + // _vault.manageUserBalance(noop); + // + // However, use a static call so that it can be a view function (even though the function is non-view). + // This allows the library to be used more widely, as some functions that need to be protected might be + // view. + // + // This staticcall always reverts, but we need to make sure it doesn't fail due to a re-entrancy attack. + // Staticcalls consume all gas forwarded to them on a revert caused by storage modification. + // By default, almost the entire available gas is forwarded to the staticcall, + // causing the entire call to revert with an 'out of gas' error. + // + // We set the gas limit to 10k for the staticcall to + // avoid wasting gas when it reverts due to storage modification. + // `manageUserBalance` is a non-reentrant function in the Vault, so calling it invokes `_enterNonReentrant` + // in the `ReentrancyGuard` contract, reproduced here: + // + // function _enterNonReentrant() private { + // // If the Vault is actually being reentered, it will revert in the first line, at the `_require` that + // // checks the reentrancy flag, with "BAL#400" (corresponding to Errors.REENTRANCY) in the revertData. + // // The full revertData will be: `abi.encodeWithSignature("Error(string)", "BAL#400")`. + // _require(_status != _ENTERED, Errors.REENTRANCY); + // + // // If the Vault is not being reentered, the check above will pass: but it will *still* revert, + // // because the next line attempts to modify storage during a staticcall. However, this type of + // // failure results in empty revertData. + // _status = _ENTERED; + // } + // + // So based on this analysis, there are only two possible revertData values: empty, or abi.encoded BAL#400. + // + // It is of course much more bytecode and gas efficient to check for zero-length revertData than to compare it + // to the encoded REENTRANCY revertData. + // + // While it should be impossible for the call to fail in any other way (especially since it reverts before + // `manageUserBalance` even gets called), any other error would generate non-zero revertData, so checking for + // empty data guards against this case too. + + (, bytes memory revertData) = address(vault).staticcall{ gas: 10_000 }( + abi.encodeWithSelector(vault.manageUserBalance.selector, 0) + ); + + _require(revertData.length == 0, Errors.REENTRANCY); + } +} diff --git a/contracts/contracts/utils/BalancerErrors.sol b/contracts/contracts/utils/BalancerErrors.sol new file mode 100644 index 0000000000..b9355b0a1a --- /dev/null +++ b/contracts/contracts/utils/BalancerErrors.sol @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pragma solidity >=0.7.1 <0.9.0; + +// solhint-disable + +/** + * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are + * supported. + * Uses the default 'BAL' prefix for the error code + */ +function _require(bool condition, uint256 errorCode) pure { + if (!condition) _revert(errorCode); +} + +/** + * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are + * supported. + */ +function _require( + bool condition, + uint256 errorCode, + bytes3 prefix +) pure { + if (!condition) _revert(errorCode, prefix); +} + +/** + * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported. + * Uses the default 'BAL' prefix for the error code + */ +function _revert(uint256 errorCode) pure { + _revert(errorCode, 0x42414c); // This is the raw byte representation of "BAL" +} + +/** + * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported. + */ +function _revert(uint256 errorCode, bytes3 prefix) pure { + uint256 prefixUint = uint256(uint24(prefix)); + // We're going to dynamically create a revert string based on the error code, with the following format: + // 'BAL#{errorCode}' + // where the code is left-padded with zeroes to three digits (so they range from 000 to 999). + // + // We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a + // number (8 to 16 bits) than the individual string characters. + // + // The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a + // much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a + // safe place to rely on it without worrying about how its usage might affect e.g. memory contents. + assembly { + // First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999 + // range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for + // the '0' character. + + let units := add(mod(errorCode, 10), 0x30) + + errorCode := div(errorCode, 10) + let tenths := add(mod(errorCode, 10), 0x30) + + errorCode := div(errorCode, 10) + let hundreds := add(mod(errorCode, 10), 0x30) + + // With the individual characters, we can now construct the full string. + // We first append the '#' character (0x23) to the prefix. In the case of 'BAL', it results in 0x42414c23 ('BAL#') + // Then, we shift this by 24 (to provide space for the 3 bytes of the error code), and add the + // characters to it, each shifted by a multiple of 8. + // The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits + // per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte + // array). + let formattedPrefix := shl(24, add(0x23, shl(8, prefixUint))) + + let revertReason := shl( + 200, + add( + formattedPrefix, + add(add(units, shl(8, tenths)), shl(16, hundreds)) + ) + ) + + // We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded + // message will have the following layout: + // [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ] + + // The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We + // also write zeroes to the next 28 bytes of memory, but those are about to be overwritten. + mstore( + 0x0, + 0x08c379a000000000000000000000000000000000000000000000000000000000 + ) + // Next is the offset to the location of the string, which will be placed immediately after (20 bytes away). + mstore( + 0x04, + 0x0000000000000000000000000000000000000000000000000000000000000020 + ) + // The string length is fixed: 7 characters. + mstore(0x24, 7) + // Finally, the string itself is stored. + mstore(0x44, revertReason) + + // Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of + // the encoded message is therefore 4 + 32 + 32 + 32 = 100. + revert(0, 100) + } +} + +library Errors { + // Math + uint256 internal constant ADD_OVERFLOW = 0; + uint256 internal constant SUB_OVERFLOW = 1; + uint256 internal constant SUB_UNDERFLOW = 2; + uint256 internal constant MUL_OVERFLOW = 3; + uint256 internal constant ZERO_DIVISION = 4; + uint256 internal constant DIV_INTERNAL = 5; + uint256 internal constant X_OUT_OF_BOUNDS = 6; + uint256 internal constant Y_OUT_OF_BOUNDS = 7; + uint256 internal constant PRODUCT_OUT_OF_BOUNDS = 8; + uint256 internal constant INVALID_EXPONENT = 9; + + // Input + uint256 internal constant OUT_OF_BOUNDS = 100; + uint256 internal constant UNSORTED_ARRAY = 101; + uint256 internal constant UNSORTED_TOKENS = 102; + uint256 internal constant INPUT_LENGTH_MISMATCH = 103; + uint256 internal constant ZERO_TOKEN = 104; + uint256 internal constant INSUFFICIENT_DATA = 105; + + // Shared pools + uint256 internal constant MIN_TOKENS = 200; + uint256 internal constant MAX_TOKENS = 201; + uint256 internal constant MAX_SWAP_FEE_PERCENTAGE = 202; + uint256 internal constant MIN_SWAP_FEE_PERCENTAGE = 203; + uint256 internal constant MINIMUM_BPT = 204; + uint256 internal constant CALLER_NOT_VAULT = 205; + uint256 internal constant UNINITIALIZED = 206; + uint256 internal constant BPT_IN_MAX_AMOUNT = 207; + uint256 internal constant BPT_OUT_MIN_AMOUNT = 208; + uint256 internal constant EXPIRED_PERMIT = 209; + uint256 internal constant NOT_TWO_TOKENS = 210; + uint256 internal constant DISABLED = 211; + + // Pools + uint256 internal constant MIN_AMP = 300; + uint256 internal constant MAX_AMP = 301; + uint256 internal constant MIN_WEIGHT = 302; + uint256 internal constant MAX_STABLE_TOKENS = 303; + uint256 internal constant MAX_IN_RATIO = 304; + uint256 internal constant MAX_OUT_RATIO = 305; + uint256 internal constant MIN_BPT_IN_FOR_TOKEN_OUT = 306; + uint256 internal constant MAX_OUT_BPT_FOR_TOKEN_IN = 307; + uint256 internal constant NORMALIZED_WEIGHT_INVARIANT = 308; + uint256 internal constant INVALID_TOKEN = 309; + uint256 internal constant UNHANDLED_JOIN_KIND = 310; + uint256 internal constant ZERO_INVARIANT = 311; + uint256 internal constant ORACLE_INVALID_SECONDS_QUERY = 312; + uint256 internal constant ORACLE_NOT_INITIALIZED = 313; + uint256 internal constant ORACLE_QUERY_TOO_OLD = 314; + uint256 internal constant ORACLE_INVALID_INDEX = 315; + uint256 internal constant ORACLE_BAD_SECS = 316; + uint256 internal constant AMP_END_TIME_TOO_CLOSE = 317; + uint256 internal constant AMP_ONGOING_UPDATE = 318; + uint256 internal constant AMP_RATE_TOO_HIGH = 319; + uint256 internal constant AMP_NO_ONGOING_UPDATE = 320; + uint256 internal constant STABLE_INVARIANT_DIDNT_CONVERGE = 321; + uint256 internal constant STABLE_GET_BALANCE_DIDNT_CONVERGE = 322; + uint256 internal constant RELAYER_NOT_CONTRACT = 323; + uint256 internal constant BASE_POOL_RELAYER_NOT_CALLED = 324; + uint256 internal constant REBALANCING_RELAYER_REENTERED = 325; + uint256 internal constant GRADUAL_UPDATE_TIME_TRAVEL = 326; + uint256 internal constant SWAPS_DISABLED = 327; + uint256 internal constant CALLER_IS_NOT_LBP_OWNER = 328; + uint256 internal constant PRICE_RATE_OVERFLOW = 329; + uint256 internal constant INVALID_JOIN_EXIT_KIND_WHILE_SWAPS_DISABLED = 330; + uint256 internal constant WEIGHT_CHANGE_TOO_FAST = 331; + uint256 internal constant LOWER_GREATER_THAN_UPPER_TARGET = 332; + uint256 internal constant UPPER_TARGET_TOO_HIGH = 333; + uint256 internal constant UNHANDLED_BY_LINEAR_POOL = 334; + uint256 internal constant OUT_OF_TARGET_RANGE = 335; + uint256 internal constant UNHANDLED_EXIT_KIND = 336; + uint256 internal constant UNAUTHORIZED_EXIT = 337; + uint256 internal constant MAX_MANAGEMENT_SWAP_FEE_PERCENTAGE = 338; + uint256 internal constant UNHANDLED_BY_MANAGED_POOL = 339; + uint256 internal constant UNHANDLED_BY_PHANTOM_POOL = 340; + uint256 internal constant TOKEN_DOES_NOT_HAVE_RATE_PROVIDER = 341; + uint256 internal constant INVALID_INITIALIZATION = 342; + uint256 internal constant OUT_OF_NEW_TARGET_RANGE = 343; + uint256 internal constant FEATURE_DISABLED = 344; + uint256 internal constant UNINITIALIZED_POOL_CONTROLLER = 345; + uint256 internal constant SET_SWAP_FEE_DURING_FEE_CHANGE = 346; + uint256 internal constant SET_SWAP_FEE_PENDING_FEE_CHANGE = 347; + uint256 internal constant CHANGE_TOKENS_DURING_WEIGHT_CHANGE = 348; + uint256 internal constant CHANGE_TOKENS_PENDING_WEIGHT_CHANGE = 349; + uint256 internal constant MAX_WEIGHT = 350; + uint256 internal constant UNAUTHORIZED_JOIN = 351; + uint256 internal constant MAX_MANAGEMENT_AUM_FEE_PERCENTAGE = 352; + uint256 internal constant FRACTIONAL_TARGET = 353; + uint256 internal constant ADD_OR_REMOVE_BPT = 354; + uint256 internal constant INVALID_CIRCUIT_BREAKER_BOUNDS = 355; + uint256 internal constant CIRCUIT_BREAKER_TRIPPED = 356; + uint256 internal constant MALICIOUS_QUERY_REVERT = 357; + uint256 internal constant JOINS_EXITS_DISABLED = 358; + + // Lib + uint256 internal constant REENTRANCY = 400; + uint256 internal constant SENDER_NOT_ALLOWED = 401; + uint256 internal constant PAUSED = 402; + uint256 internal constant PAUSE_WINDOW_EXPIRED = 403; + uint256 internal constant MAX_PAUSE_WINDOW_DURATION = 404; + uint256 internal constant MAX_BUFFER_PERIOD_DURATION = 405; + uint256 internal constant INSUFFICIENT_BALANCE = 406; + uint256 internal constant INSUFFICIENT_ALLOWANCE = 407; + uint256 internal constant ERC20_TRANSFER_FROM_ZERO_ADDRESS = 408; + uint256 internal constant ERC20_TRANSFER_TO_ZERO_ADDRESS = 409; + uint256 internal constant ERC20_MINT_TO_ZERO_ADDRESS = 410; + uint256 internal constant ERC20_BURN_FROM_ZERO_ADDRESS = 411; + uint256 internal constant ERC20_APPROVE_FROM_ZERO_ADDRESS = 412; + uint256 internal constant ERC20_APPROVE_TO_ZERO_ADDRESS = 413; + uint256 internal constant ERC20_TRANSFER_EXCEEDS_ALLOWANCE = 414; + uint256 internal constant ERC20_DECREASED_ALLOWANCE_BELOW_ZERO = 415; + uint256 internal constant ERC20_TRANSFER_EXCEEDS_BALANCE = 416; + uint256 internal constant ERC20_BURN_EXCEEDS_ALLOWANCE = 417; + uint256 internal constant SAFE_ERC20_CALL_FAILED = 418; + uint256 internal constant ADDRESS_INSUFFICIENT_BALANCE = 419; + uint256 internal constant ADDRESS_CANNOT_SEND_VALUE = 420; + uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_INT256 = 421; + uint256 internal constant GRANT_SENDER_NOT_ADMIN = 422; + uint256 internal constant REVOKE_SENDER_NOT_ADMIN = 423; + uint256 internal constant RENOUNCE_SENDER_NOT_ALLOWED = 424; + uint256 internal constant BUFFER_PERIOD_EXPIRED = 425; + uint256 internal constant CALLER_IS_NOT_OWNER = 426; + uint256 internal constant NEW_OWNER_IS_ZERO = 427; + uint256 internal constant CODE_DEPLOYMENT_FAILED = 428; + uint256 internal constant CALL_TO_NON_CONTRACT = 429; + uint256 internal constant LOW_LEVEL_CALL_FAILED = 430; + uint256 internal constant NOT_PAUSED = 431; + uint256 internal constant ADDRESS_ALREADY_ALLOWLISTED = 432; + uint256 internal constant ADDRESS_NOT_ALLOWLISTED = 433; + uint256 internal constant ERC20_BURN_EXCEEDS_BALANCE = 434; + uint256 internal constant INVALID_OPERATION = 435; + uint256 internal constant CODEC_OVERFLOW = 436; + uint256 internal constant IN_RECOVERY_MODE = 437; + uint256 internal constant NOT_IN_RECOVERY_MODE = 438; + uint256 internal constant INDUCED_FAILURE = 439; + uint256 internal constant EXPIRED_SIGNATURE = 440; + uint256 internal constant MALFORMED_SIGNATURE = 441; + uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_UINT64 = 442; + uint256 internal constant UNHANDLED_FEE_TYPE = 443; + uint256 internal constant BURN_FROM_ZERO = 444; + + // Vault + uint256 internal constant INVALID_POOL_ID = 500; + uint256 internal constant CALLER_NOT_POOL = 501; + uint256 internal constant SENDER_NOT_ASSET_MANAGER = 502; + uint256 internal constant USER_DOESNT_ALLOW_RELAYER = 503; + uint256 internal constant INVALID_SIGNATURE = 504; + uint256 internal constant EXIT_BELOW_MIN = 505; + uint256 internal constant JOIN_ABOVE_MAX = 506; + uint256 internal constant SWAP_LIMIT = 507; + uint256 internal constant SWAP_DEADLINE = 508; + uint256 internal constant CANNOT_SWAP_SAME_TOKEN = 509; + uint256 internal constant UNKNOWN_AMOUNT_IN_FIRST_SWAP = 510; + uint256 internal constant MALCONSTRUCTED_MULTIHOP_SWAP = 511; + uint256 internal constant INTERNAL_BALANCE_OVERFLOW = 512; + uint256 internal constant INSUFFICIENT_INTERNAL_BALANCE = 513; + uint256 internal constant INVALID_ETH_INTERNAL_BALANCE = 514; + uint256 internal constant INVALID_POST_LOAN_BALANCE = 515; + uint256 internal constant INSUFFICIENT_ETH = 516; + uint256 internal constant UNALLOCATED_ETH = 517; + uint256 internal constant ETH_TRANSFER = 518; + uint256 internal constant CANNOT_USE_ETH_SENTINEL = 519; + uint256 internal constant TOKENS_MISMATCH = 520; + uint256 internal constant TOKEN_NOT_REGISTERED = 521; + uint256 internal constant TOKEN_ALREADY_REGISTERED = 522; + uint256 internal constant TOKENS_ALREADY_SET = 523; + uint256 internal constant TOKENS_LENGTH_MUST_BE_2 = 524; + uint256 internal constant NONZERO_TOKEN_BALANCE = 525; + uint256 internal constant BALANCE_TOTAL_OVERFLOW = 526; + uint256 internal constant POOL_NO_TOKENS = 527; + uint256 internal constant INSUFFICIENT_FLASH_LOAN_BALANCE = 528; + + // Fees + uint256 internal constant SWAP_FEE_PERCENTAGE_TOO_HIGH = 600; + uint256 internal constant FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH = 601; + uint256 internal constant INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT = 602; + uint256 internal constant AUM_FEE_PERCENTAGE_TOO_HIGH = 603; + + // FeeSplitter + uint256 internal constant SPLITTER_FEE_PERCENTAGE_TOO_HIGH = 700; + + // Misc + uint256 internal constant UNIMPLEMENTED = 998; + uint256 internal constant SHOULD_NOT_HAPPEN = 999; +} From c6b45c378f049ed322d4b2f17176e523a06421b6 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 24 Jul 2023 14:24:55 +0200 Subject: [PATCH 18/67] add some missing tests and adjust existing. Deparate deposit and withdrawal slippage --- .../balancer/BalancerMetaPoolStrategy.sol | 14 ++------ .../strategies/balancer/BaseAuraStrategy.sol | 2 +- .../balancer/BaseBalancerStrategy.sol | 30 +++++++++++++++- .../balancerMetaStablePool.fork-test.js | 34 +++++++++++++++++-- 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index c36fe95593..15d93b2163 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -88,8 +88,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { return; } - //TODO: re-entrency protection - emit Deposit(_asset, pTokenAddress, _amount); (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); @@ -97,6 +95,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( balancerPoolId ); + + // TODO: refactor this bit and withdrawal bit to create amounts for in/out array uint256 tokensLength = tokens.length; uint256[] memory maxAmountsIn = new uint256[](tokensLength); uint256 assetIndex = 0; @@ -112,9 +112,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { wrapPoolAsset(_asset, _amount); uint256 minBPT = getBPTExpected(_asset, _amount); - uint256 minBPTwSlippage = minBPT.mulTruncate( - 1e18 - maxWithdrawalSlippage - ); + uint256 minBPTwSlippage = minBPT.mulTruncate(1e18 - maxDepositSlippage); /* TOKEN_IN_FOR_EXACT_BPT_OUT: * User sends an estimated but unknown (computed at run time) quantity of a single token, @@ -155,9 +153,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { _lpWithdraw(BPTtoWithdraw); - //TODO: re-entrency protection - - // TODO refactor this bit (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( balancerPoolId ); @@ -215,9 +210,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address(this) ); - //TODO: re-entrency protection - - // TODO refactor this bit (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault .getPoolTokens(balancerPoolId); diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index b54bedcd05..333d53338f 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -55,6 +55,7 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { auraDepositorPTokenId = initConfig.auraDepositorPTokenId; pTokenAddress = _pTokens[0]; maxWithdrawalSlippage = 1e15; + maxDepositSlippage = 1e15; balancerPoolId = initConfig.balancerPoolId; IERC20[] memory poolAssets = getPoolAssets(); uint256 assetsLength = _assets.length; @@ -68,7 +69,6 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { _assets[i] == asset, "Pool assets and _assets should all have the same numerical order." ); - // TODO: double check if this fits in here poolAssetsMapped.push(address(poolAssets[i])); } diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index ef4dc56ce0..f9efaa2b83 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -35,14 +35,20 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { bytes32 internal balancerPoolId; // Full list of all assets as they are present in the Balancer pool address[] internal poolAssetsMapped; - // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) - TODO better name also considered with deposits + // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) uint256 public maxWithdrawalSlippage; + // Max deposit slippage denominated in 1e18 (1e18 == 100%) + uint256 public maxDepositSlippage; int256[50] private __reserved; event MaxWithdrawalSlippageUpdated( uint256 _prevMaxSlippagePercentage, uint256 _newMaxSlippagePercentage ); + event MaxDepositSlippageUpdated( + uint256 _prevMaxSlippagePercentage, + uint256 _newMaxSlippagePercentage + ); /** * @dev Ensure we are not in a Vault context when this function is called, by attempting a no-op internal @@ -286,6 +292,28 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { maxWithdrawalSlippage = _maxWithdrawalSlippage; } + /** + * @dev Sets max deposit slippage that is considered when adding + * liquidity to Balancer pools. + * @param _maxDepositSlippage Max deposit slippage denominated in + * wad (number with 18 decimals): 1e18 == 100%, 1e16 == 1% + * + * IMPORTANT Minimum maxDepositSlippage should actually be 0.1% (1e15) + * for production usage. Contract allows as low value as 0% for confirming + * correct behavior in test suite. + */ + function setMaxDepositSlippage(uint256 _maxDepositSlippage) + external + onlyVaultOrGovernorOrStrategist + { + require( + _maxDepositSlippage <= 1e18, + "Max deposit slippage needs to be between 0% - 100%" + ); + emit MaxDepositSlippageUpdated(maxDepositSlippage, _maxDepositSlippage); + maxDepositSlippage = _maxDepositSlippage; + } + function _approveBase() internal virtual { IERC20 pToken = IERC20(pTokenAddress); // Balancer vault for BPT token (required for removing liquidity) diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index e4e14dce46..3549ab0dd3 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -30,6 +30,25 @@ forkOnlyDescribe( const { josh, stETH, weth } = fixture; await mintTest(fixture, josh, stETH, "30", [weth, stETH]); }); + + it("Should have the correct initial maxDepositSlippage state", async function () { + const { balancerWstEthWethStrategy, josh } = fixture; + expect( + await balancerWstEthWethStrategy.connect(josh).maxDepositSlippage() + ).to.equal(ousdUnits("0.001")); + }); + + it("Should be able to deposit with higher deposit slippage", async function () {}); + + it("Should revert when read-only re-entrancy is triggered", async function () { + /* - needs to be an asset default strategy + * - needs pool that supports native ETH + * - attacker needs to try to deposit to balancer pool and withdraw + * - while withdrawing and receiving ETH attacker should take over the execution flow + * and try calling mint/redeem with the strategy default asset on the OethVault + * - transaction should revert because of the `whenNotInVaultContext` modifier + */ + }); }); describe.only("Withdraw", function () { @@ -82,6 +101,15 @@ forkOnlyDescribe( expect(wethBalanceDiff).to.be.gte(await units("15", weth), 1); expect(stEthBalanceDiff).to.be.gte(await units("15", stETH), 1); }); + + it("Should have the correct initial maxWithdrawalSlippage state", async function () { + const { balancerWstEthWethStrategy, josh } = fixture; + expect( + await balancerWstEthWethStrategy.connect(josh).maxWithdrawalSlippage() + ).to.equal(ousdUnits("0.001")); + }); + + it("Should be able to withdraw with higher withdrawal slippage", async function () {}); }); describe.only("Harvest rewards", function () { @@ -136,7 +164,7 @@ async function mintTest(fixture, user, asset, amount, allAssets) { const balanceDiff = newBalance.sub(currentBalance); // Ensure user has correct balance (w/ 1% slippage tolerance) - expect(balanceDiff).to.approxEqualTolerance(ousdUnits(amount), 2); + expect(balanceDiff).to.approxEqualTolerance(ousdUnits(amount), 1); // Supply checks const supplyDiff = newSupply.sub(currentSupply); @@ -146,9 +174,9 @@ async function mintTest(fixture, user, asset, amount, allAssets) { const balancerLiquidityDiff = newBalancerBalance.sub(currentBalancerBalance); - // Should have liquidity in Morpho + // Should have liquidity in Balancer expect(balancerLiquidityDiff).to.approxEqualTolerance( await units(amount, asset), - 15 // TODO why such high slippage + 1 ); } From c77a296315712e19286b5aef38f902dfd8e5b921 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 24 Jul 2023 14:44:02 +0200 Subject: [PATCH 19/67] fix check balance implementation --- .../contracts/strategies/balancer/BaseAuraStrategy.sol | 6 +++++- .../test/strategies/balancerMetaStablePool.fork-test.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 333d53338f..8738bf1cfc 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -139,7 +139,11 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { for (uint256 i = 0; i < balancesLength; ++i) { (address poolAsset, ) = toPoolAsset(_asset, 0); if (address(tokens[i]) == poolAsset) { - return balances[i].mulTruncate(yourPoolShare); + (, uint256 assetAmount) = fromPoolAsset( + poolAsset, + balances[i].mulTruncate(yourPoolShare) + ); + return assetAmount; } } } diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 3549ab0dd3..ee2679d76d 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -43,7 +43,7 @@ forkOnlyDescribe( it("Should revert when read-only re-entrancy is triggered", async function () { /* - needs to be an asset default strategy * - needs pool that supports native ETH - * - attacker needs to try to deposit to balancer pool and withdraw + * - attacker needs to try to deposit to Balancer pool and withdraw * - while withdrawing and receiving ETH attacker should take over the execution flow * and try calling mint/redeem with the strategy default asset on the OethVault * - transaction should revert because of the `whenNotInVaultContext` modifier From 75329dbdda717c8d575a0f9e09616a80090fbf3a Mon Sep 17 00:00:00 2001 From: Nick Addison Date: Tue, 1 Aug 2023 06:15:00 +1000 Subject: [PATCH 20/67] Balancer review changes (#1726) * Generated contract docs * Refactor Balancer storage variables * Small Balancer changes * Natspec updates Added missing licensing getPoolAssets gas optimized * Updated generated Balancer strategy contract diagrams * fix contract linter * Removed restrictions on tests * Small gas improvements Fixed Slither * Change BalancerError version * Updated constant names Addresses to use checksum format * JS lint tasks * Updated Balancer and Aura pool id constants * Removed getRateProviderRate as it wasn't being used Refactored to remove poolAssetsMapped storage variable * Updated OETH Contracts diagrams Generated new Balancer contract diagrams * Fix failing test * Fix merge conflict * Restored getRateProviderRate * Natspec updates Added toPoolAsset override * Removed unused getRateProviderRate * Natspec updates Gas optimization of InitializableAbstractStrategy * Abstract strategy gas improvements (#1719) * Refactor base strategy to use immutables * Fixed strategy deployments in 001_core and fixtures * Generated new strategy diagrams * Deploy rETH instead of the stETH Balancer MetaStable Pool * removed unused Aura config * Balancer fork tests * Added check that BPT amount equals Aura LP amount Added rETH conversion to ETH value * Updated balancer strat fork tests * Updated Balancer fork tests * Added optional deposit with multiple assets to the strategy * Single asset deposit to use multi asset deposit * Added optional checkBalance to Balancer strategy * Added checkBalance() to BaseBalancerStrategy * Fix slither Fix curve HH task * Added multi-asset withdraw to balancer strategy * Fix multi-asset withdraw * Updated Balancer and Vault diagrams * Fix js linter * Fixed checkBalance of rETH asset in Balancer strategy * Only wrap assets if amount > 0 Added depositAll fork test for Balancer strat * Removed Vault changes for multi-asset strategy support * Updated generated docs * Add tests for wstETH/WETH Balancer pool (#1725) * Split deployment and fix fixtures * Deposit tests for wstETH/WETH pool * Add withdraw test * prettier * remove .only in fork tests --------- Co-authored-by: Shahul Hameed <10547529+shahthepro@users.noreply.github.com> --- contracts/contracts/governance/Governable.sol | 2 +- .../contracts/interfaces/IERC20Details.sol | 4 + contracts/contracts/interfaces/IRETH.sol | 35 + contracts/contracts/interfaces/IWstETH.sol | 1 + contracts/contracts/proxies/Proxies.sol | 13 +- .../contracts/strategies/AaveStrategy.sol | 13 +- .../strategies/BaseConvexMetaStrategy.sol | 11 +- .../contracts/strategies/CompoundStrategy.sol | 6 +- .../strategies/ConvexEthMetaStrategy.sol | 13 +- .../ConvexGeneralizedMetaStrategy.sol | 6 +- .../strategies/ConvexOUSDMetaStrategy.sol | 6 +- .../contracts/strategies/ConvexStrategy.sol | 18 +- .../contracts/strategies/FraxETHStrategy.sol | 7 +- .../strategies/Generalized4626Strategy.sol | 4 + .../strategies/MorphoAaveStrategy.sol | 16 +- .../strategies/MorphoCompoundStrategy.sol | 19 +- .../strategies/ThreePoolStrategy.sol | 18 +- .../balancer/BalancerMetaPoolStrategy.sol | 404 +++++++---- .../strategies/balancer/BaseAuraStrategy.sol | 109 ++- .../balancer/BaseBalancerStrategy.sol | 291 +++++--- .../contracts/strategies/balancer/README.md | 15 + contracts/contracts/utils/BalancerErrors.sol | 2 +- contracts/contracts/utils/Initializable.sol | 4 + .../utils/InitializableAbstractStrategy.sol | 104 +-- .../utils/InitializableERC20Detailed.sol | 7 +- contracts/deploy/000_mock.js | 5 - contracts/deploy/001_core.js | 74 +- contracts/deploy/057_drip_all.js | 31 +- ...tETH_WETH.js => 071_balancer_rETH_WETH.js} | 63 +- contracts/docs/AaveStrategyHierarchy.svg | 218 ++++-- contracts/docs/AaveStrategySquashed.svg | 173 ++--- contracts/docs/AaveStrategyStorage.svg | 12 +- .../BalancerMetaPoolStrategyHierarchy.svg | 329 +++++++++ .../docs/BalancerMetaPoolStrategySquashed.svg | 134 ++++ .../docs/BalancerMetaPoolStrategyStorage.svg | 285 ++++++++ contracts/docs/CompStrategyHierarchy.svg | 206 ++++-- contracts/docs/CompStrategySquashed.svg | 171 ++--- contracts/docs/CompStrategyStorage.svg | 12 +- .../docs/ConvexEthMetaStrategyHierarchy.svg | 308 ++++---- .../docs/ConvexEthMetaStrategySquashed.svg | 197 ++--- contracts/docs/FraxETHStrategyHierarchy.svg | 136 ++-- contracts/docs/FraxETHStrategySquashed.svg | 86 +-- .../docs/MorphoAaveStrategyHierarchy.svg | 294 +++++--- contracts/docs/MorphoAaveStrategySquashed.svg | 108 +-- contracts/docs/MorphoAaveStrategyStorage.svg | 12 +- .../docs/MorphoCompStrategyHierarchy.svg | 238 ++++--- contracts/docs/MorphoCompStrategySquashed.svg | 110 +-- contracts/docs/MorphoCompStrategyStorage.svg | 12 +- contracts/docs/OETHVaultAdminSquashed.svg | 256 ++++--- contracts/docs/OETHVaultCoreSquashed.svg | 257 ++++--- contracts/docs/OETHVaultHierarchy.svg | 92 +-- contracts/docs/VaultAdminSquashed.svg | 256 ++++--- contracts/docs/VaultCoreSquashed.svg | 257 ++++--- contracts/docs/VaultHierarchy.svg | 124 ++-- contracts/docs/generate.sh | 5 + contracts/docs/plantuml/oethContracts.png | Bin 57821 -> 68878 bytes contracts/docs/plantuml/oethContracts.puml | 14 +- contracts/package.json | 2 +- contracts/tasks/account.js | 6 +- contracts/tasks/curve.js | 11 +- contracts/tasks/smokeTest.js | 8 +- contracts/tasks/storageSlots.js | 4 +- contracts/tasks/tasks.js | 4 +- contracts/tasks/vault.js | 6 +- contracts/test/_fixture.js | 174 +++-- contracts/test/helpers.js | 6 +- .../balancerMetaStablePool.fork-test.js | 670 +++++++++++++++--- contracts/utils/addresses.js | 31 +- contracts/utils/balancerStrategyDeployment.js | 125 ++++ contracts/utils/constants.js | 32 +- 70 files changed, 4401 insertions(+), 2281 deletions(-) create mode 100644 contracts/contracts/interfaces/IERC20Details.sol create mode 100644 contracts/contracts/interfaces/IRETH.sol create mode 100644 contracts/contracts/strategies/balancer/README.md rename contracts/deploy/{071_balancer_wstETH_WETH.js => 071_balancer_rETH_WETH.js} (67%) create mode 100644 contracts/docs/BalancerMetaPoolStrategyHierarchy.svg create mode 100644 contracts/docs/BalancerMetaPoolStrategySquashed.svg create mode 100644 contracts/docs/BalancerMetaPoolStrategyStorage.svg create mode 100644 contracts/utils/balancerStrategyDeployment.js diff --git a/contracts/contracts/governance/Governable.sol b/contracts/contracts/governance/Governable.sol index a3af7db60d..15f33ec9a2 100644 --- a/contracts/contracts/governance/Governable.sol +++ b/contracts/contracts/governance/Governable.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; /** - * @title OUSD Governable Contract + * @title Base for contracts that are managed by the Origin Protocol's Governor. * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change * from owner to governor and renounce methods removed. Does not use * Context.sol like Ownable.sol does for simplification. diff --git a/contracts/contracts/interfaces/IERC20Details.sol b/contracts/contracts/interfaces/IERC20Details.sol new file mode 100644 index 0000000000..117f5b2e5b --- /dev/null +++ b/contracts/contracts/interfaces/IERC20Details.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; diff --git a/contracts/contracts/interfaces/IRETH.sol b/contracts/contracts/interfaces/IRETH.sol new file mode 100644 index 0000000000..c4fe5db32d --- /dev/null +++ b/contracts/contracts/interfaces/IRETH.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IRETH { + function getEthValue(uint256 _rethAmount) external view returns (uint256); + + function getRethValue(uint256 _ethAmount) external view returns (uint256); + + function totalSupply() external view returns (uint256); + + function balanceOf(address account) external view returns (uint256); + + function transfer(address recipient, uint256 amount) + external + returns (bool); + + function allowance(address owner, address spender) + external + view + returns (uint256); + + function approve(address spender, uint256 amount) external returns (bool); + + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external returns (bool); + + function name() external view returns (string memory); + + function symbol() external view returns (string memory); + + function decimals() external view returns (uint8); +} diff --git a/contracts/contracts/interfaces/IWstETH.sol b/contracts/contracts/interfaces/IWstETH.sol index 467a81c297..aae673c3bf 100644 --- a/contracts/contracts/interfaces/IWstETH.sol +++ b/contracts/contracts/interfaces/IWstETH.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IWstETH { diff --git a/contracts/contracts/proxies/Proxies.sol b/contracts/contracts/proxies/Proxies.sol index 898f958527..f196b1b5a8 100644 --- a/contracts/contracts/proxies/Proxies.sol +++ b/contracts/contracts/proxies/Proxies.sol @@ -158,9 +158,18 @@ contract OETHMorphoAaveStrategyProxy is InitializeGovernedUpgradeabilityProxy { } /** - * @notice OETHBalancerMetaPoolStrategyProxy delegates calls to a BalancerMetaPoolStrategy implementation + * @notice OETHBalancerMetaPoolrEthStrategyProxy delegates calls to a BalancerMetaPoolStrategy implementation */ -contract OETHBalancerMetaPoolWstEthWethStrategyProxy is +contract OETHBalancerMetaPoolrEthStrategyProxy is + InitializeGovernedUpgradeabilityProxy +{ + +} + +/** + * @notice OETHBalancerMetaPoolwstEthStrategyProxy delegates calls to a BalancerMetaPoolStrategy implementation + */ +contract OETHBalancerMetaPoolwstEthStrategyProxy is InitializeGovernedUpgradeabilityProxy { diff --git a/contracts/contracts/strategies/AaveStrategy.sol b/contracts/contracts/strategies/AaveStrategy.sol index 85f56dc112..e8eb623eaa 100644 --- a/contracts/contracts/strategies/AaveStrategy.sol +++ b/contracts/contracts/strategies/AaveStrategy.sol @@ -22,12 +22,17 @@ contract AaveStrategy is InitializableAbstractStrategy { IAaveIncentivesController public incentivesController; IAaveStakedToken public stkAave; + /** + * @param _stratConfig The platform and OToken vault addresses + */ + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /** * Initializer for setting up strategy internal state. This overrides the * InitializableAbstractStrategy initializer as AAVE needs several extra * addresses for the rewards program. - * @param _platformAddress Address of the AAVE pool - * @param _vaultAddress Address of the vault * @param _rewardTokenAddresses Address of the AAVE token * @param _assets Addresses of supported assets * @param _pTokens Platform Token corresponding addresses @@ -35,8 +40,6 @@ contract AaveStrategy is InitializableAbstractStrategy { * @param _stkAaveAddress Address of the stkAave contract */ function initialize( - address _platformAddress, // AAVE pool - address _vaultAddress, address[] calldata _rewardTokenAddresses, // AAVE address[] calldata _assets, address[] calldata _pTokens, @@ -46,8 +49,6 @@ contract AaveStrategy is InitializableAbstractStrategy { incentivesController = IAaveIncentivesController(_incentivesAddress); stkAave = IAaveStakedToken(_stkAaveAddress); InitializableAbstractStrategy._initialize( - _platformAddress, - _vaultAddress, _rewardTokenAddresses, _assets, _pTokens diff --git a/contracts/contracts/strategies/BaseConvexMetaStrategy.sol b/contracts/contracts/strategies/BaseConvexMetaStrategy.sol index 87a8f6ce12..ecb5d5b9b0 100644 --- a/contracts/contracts/strategies/BaseConvexMetaStrategy.sol +++ b/contracts/contracts/strategies/BaseConvexMetaStrategy.sol @@ -18,6 +18,7 @@ import { Helpers } from "../utils/Helpers.sol"; abstract contract BaseConvexMetaStrategy is BaseCurveStrategy { using StableMath for uint256; using SafeERC20 for IERC20; + event MaxWithdrawalSlippageUpdated( uint256 _prevMaxSlippagePercentage, uint256 _newMaxSlippagePercentage @@ -25,8 +26,6 @@ abstract contract BaseConvexMetaStrategy is BaseCurveStrategy { // used to circumvent the stack too deep issue struct InitConfig { - address platformAddress; //Address of the Curve 3pool - address vaultAddress; //Address of the vault address cvxDepositorAddress; //Address of the Convex depositor(AKA booster) for this pool address metapoolAddress; //Address of the Curve MetaPool address metapoolMainToken; //Address of Main metapool token @@ -82,13 +81,7 @@ abstract contract BaseConvexMetaStrategy is BaseCurveStrategy { metapoolAssets = [metapool.coins(0), metapool.coins(1)]; crvCoinIndex = _getMetapoolCoinIndex(pTokenAddress); mainCoinIndex = _getMetapoolCoinIndex(initConfig.metapoolMainToken); - super._initialize( - initConfig.platformAddress, - initConfig.vaultAddress, - _rewardTokenAddresses, - _assets, - _pTokens - ); + super._initialize(_rewardTokenAddresses, _assets, _pTokens); _approveBase(); } diff --git a/contracts/contracts/strategies/CompoundStrategy.sol b/contracts/contracts/strategies/CompoundStrategy.sol index e615235954..65f8d46907 100644 --- a/contracts/contracts/strategies/CompoundStrategy.sol +++ b/contracts/contracts/strategies/CompoundStrategy.sol @@ -9,7 +9,7 @@ pragma solidity ^0.8.0; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { ICERC20 } from "./ICompound.sol"; -import { BaseCompoundStrategy } from "./BaseCompoundStrategy.sol"; +import { BaseCompoundStrategy, InitializableAbstractStrategy } from "./BaseCompoundStrategy.sol"; import { IComptroller } from "../interfaces/IComptroller.sol"; import { IERC20 } from "../utils/InitializableAbstractStrategy.sol"; @@ -17,6 +17,10 @@ contract CompoundStrategy is BaseCompoundStrategy { using SafeERC20 for IERC20; event SkippedWithdrawal(address asset, uint256 amount); + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /** * @dev Collect accumulated COMP and send to Harvester. */ diff --git a/contracts/contracts/strategies/ConvexEthMetaStrategy.sol b/contracts/contracts/strategies/ConvexEthMetaStrategy.sol index cf40c66df0..79e4b4eb1e 100644 --- a/contracts/contracts/strategies/ConvexEthMetaStrategy.sol +++ b/contracts/contracts/strategies/ConvexEthMetaStrategy.sol @@ -38,7 +38,6 @@ contract ConvexEthMetaStrategy is InitializableAbstractStrategy { // used to circumvent the stack too deep issue struct InitializeConfig { address curvePoolAddress; //Address of the Curve pool - address vaultAddress; //Address of the vault address cvxDepositorAddress; //Address of the Convex depositor(AKA booster) for this pool address oethAddress; //Address of OETH token address cvxRewardStakerAddress; //Address of the CVX rewards staker @@ -46,6 +45,10 @@ contract ConvexEthMetaStrategy is InitializableAbstractStrategy { uint256 cvxDepositorPTokenId; //Pid of the pool referred to by Depositor and staker } + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /** * Initializer for setting up strategy internal state. This overrides the * InitializableAbstractStrategy initializer as Curve strategies don't fit @@ -75,13 +78,7 @@ contract ConvexEthMetaStrategy is InitializableAbstractStrategy { ethCoinIndex = uint128(_getCoinIndex(ETH_ADDRESS)); oethCoinIndex = uint128(_getCoinIndex(initConfig.oethAddress)); - super._initialize( - initConfig.curvePoolAddress, - initConfig.vaultAddress, - _rewardTokenAddresses, - _assets, - _pTokens - ); + super._initialize(_rewardTokenAddresses, _assets, _pTokens); /* needs to be called after super._initialize so that the platformAddress * is correctly set diff --git a/contracts/contracts/strategies/ConvexGeneralizedMetaStrategy.sol b/contracts/contracts/strategies/ConvexGeneralizedMetaStrategy.sol index 2dbed89c36..e56aa03aa2 100644 --- a/contracts/contracts/strategies/ConvexGeneralizedMetaStrategy.sol +++ b/contracts/contracts/strategies/ConvexGeneralizedMetaStrategy.sol @@ -12,7 +12,7 @@ import "@openzeppelin/contracts/utils/Strings.sol"; import { IRewardStaking } from "./IRewardStaking.sol"; import { IConvexDeposits } from "./IConvexDeposits.sol"; import { ICurvePool } from "./ICurvePool.sol"; -import { IERC20 } from "./BaseCurveStrategy.sol"; +import { IERC20, InitializableAbstractStrategy } from "./BaseCurveStrategy.sol"; import { BaseConvexMetaStrategy } from "./BaseConvexMetaStrategy.sol"; import { StableMath } from "../utils/StableMath.sol"; @@ -20,6 +20,10 @@ contract ConvexGeneralizedMetaStrategy is BaseConvexMetaStrategy { using StableMath for uint256; using SafeERC20 for IERC20; + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /* Take 3pool LP and deposit it to metapool. Take the LP from metapool * and deposit them to Convex. */ diff --git a/contracts/contracts/strategies/ConvexOUSDMetaStrategy.sol b/contracts/contracts/strategies/ConvexOUSDMetaStrategy.sol index 34a1313eb0..742e8050b1 100644 --- a/contracts/contracts/strategies/ConvexOUSDMetaStrategy.sol +++ b/contracts/contracts/strategies/ConvexOUSDMetaStrategy.sol @@ -13,7 +13,7 @@ import "@openzeppelin/contracts/utils/math/Math.sol"; import { IRewardStaking } from "./IRewardStaking.sol"; import { IConvexDeposits } from "./IConvexDeposits.sol"; import { ICurvePool } from "./ICurvePool.sol"; -import { IERC20 } from "./BaseCurveStrategy.sol"; +import { IERC20, InitializableAbstractStrategy } from "./BaseCurveStrategy.sol"; import { BaseConvexMetaStrategy } from "./BaseConvexMetaStrategy.sol"; import { StableMath } from "../utils/StableMath.sol"; import { IVault } from "../interfaces/IVault.sol"; @@ -22,6 +22,10 @@ contract ConvexOUSDMetaStrategy is BaseConvexMetaStrategy { using StableMath for uint256; using SafeERC20 for IERC20; + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /* Take 3pool LP and mint the corresponding amount of ousd. Deposit and stake that to * ousd Curve Metapool. Take the LP from metapool and deposit them to Convex. */ diff --git a/contracts/contracts/strategies/ConvexStrategy.sol b/contracts/contracts/strategies/ConvexStrategy.sol index e4f82ca4b9..d8350ed943 100644 --- a/contracts/contracts/strategies/ConvexStrategy.sol +++ b/contracts/contracts/strategies/ConvexStrategy.sol @@ -11,7 +11,7 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s import { ICurvePool } from "./ICurvePool.sol"; import { IRewardStaking } from "./IRewardStaking.sol"; import { IConvexDeposits } from "./IConvexDeposits.sol"; -import { IERC20, BaseCurveStrategy } from "./BaseCurveStrategy.sol"; +import { IERC20, BaseCurveStrategy, InitializableAbstractStrategy } from "./BaseCurveStrategy.sol"; import { StableMath } from "../utils/StableMath.sol"; import { Helpers } from "../utils/Helpers.sol"; @@ -32,12 +32,14 @@ contract ConvexStrategy is BaseCurveStrategy { address public _deprecated_cvxRewardTokenAddress; uint256 internal cvxDepositorPTokenId; + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /** * Initializer for setting up strategy internal state. This overrides the * InitializableAbstractStrategy initializer as Curve strategies don't fit * well within that abstraction. - * @param _platformAddress Address of the Curve 3pool - * @param _vaultAddress Address of the vault * @param _rewardTokenAddresses Address of CRV & CVX * @param _assets Addresses of supported assets. MUST be passed in the same * order as returned by coins on the pool contract, i.e. @@ -48,8 +50,6 @@ contract ConvexStrategy is BaseCurveStrategy { * @param _cvxDepositorPTokenId Pid of the pool referred to by Depositor and staker */ function initialize( - address _platformAddress, // 3Pool address - address _vaultAddress, address[] calldata _rewardTokenAddresses, // CRV + CVX address[] calldata _assets, address[] calldata _pTokens, @@ -65,13 +65,7 @@ contract ConvexStrategy is BaseCurveStrategy { cvxDepositorPTokenId = _cvxDepositorPTokenId; pTokenAddress = _pTokens[0]; - super._initialize( - _platformAddress, - _vaultAddress, - _rewardTokenAddresses, - _assets, - _pTokens - ); + super._initialize(_rewardTokenAddresses, _assets, _pTokens); _approveBase(); } diff --git a/contracts/contracts/strategies/FraxETHStrategy.sol b/contracts/contracts/strategies/FraxETHStrategy.sol index 48b5831268..fc25b1ae74 100644 --- a/contracts/contracts/strategies/FraxETHStrategy.sol +++ b/contracts/contracts/strategies/FraxETHStrategy.sol @@ -8,10 +8,9 @@ pragma solidity ^0.8.0; */ import { IERC4626 } from "../../lib/openzeppelin/interfaces/IERC4626.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { IERC20 } from "../utils/InitializableAbstractStrategy.sol"; import { IWETH9 } from "../interfaces/IWETH9.sol"; import { IFraxETHMinter } from "../interfaces/IFraxETHMinter.sol"; -import { Generalized4626Strategy } from "./Generalized4626Strategy.sol"; +import { Generalized4626Strategy, IERC20 } from "./Generalized4626Strategy.sol"; contract FraxETHStrategy is Generalized4626Strategy { using SafeERC20 for IERC20; @@ -21,6 +20,10 @@ contract FraxETHStrategy is Generalized4626Strategy { IFraxETHMinter public constant fraxETHMinter = IFraxETHMinter(0xbAFA44EFE7901E04E39Dad13167D089C559c1138); + constructor(BaseStrategyConfig memory _stratConfig) + Generalized4626Strategy(_stratConfig) + {} + function _deposit(address _asset, uint256 _amount) internal override { require(_amount > 0, "Must deposit something"); diff --git a/contracts/contracts/strategies/Generalized4626Strategy.sol b/contracts/contracts/strategies/Generalized4626Strategy.sol index eb0fa13257..5388ab82dc 100644 --- a/contracts/contracts/strategies/Generalized4626Strategy.sol +++ b/contracts/contracts/strategies/Generalized4626Strategy.sol @@ -19,6 +19,10 @@ contract Generalized4626Strategy is InitializableAbstractStrategy { // For future use uint256[50] private __gap; + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /** * @dev Deposit assets by converting them to shares * @param _asset Address of asset to deposit diff --git a/contracts/contracts/strategies/MorphoAaveStrategy.sol b/contracts/contracts/strategies/MorphoAaveStrategy.sol index 8961a2ea62..5ec02e2776 100644 --- a/contracts/contracts/strategies/MorphoAaveStrategy.sol +++ b/contracts/contracts/strategies/MorphoAaveStrategy.sol @@ -19,26 +19,22 @@ contract MorphoAaveStrategy is InitializableAbstractStrategy { using SafeERC20 for IERC20; using StableMath for uint256; + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /** * @dev Initialize function, to set up initial internal state - * @param _vaultAddress Address of the Vault * @param _rewardTokenAddresses Address of reward token for platform * @param _assets Addresses of initial supported assets * @param _pTokens Platform Token corresponding addresses */ function initialize( - address _vaultAddress, address[] calldata _rewardTokenAddresses, address[] calldata _assets, address[] calldata _pTokens - ) external onlyGovernor initializer { - super._initialize( - MORPHO, - _vaultAddress, - _rewardTokenAddresses, - _assets, - _pTokens - ); + ) external override onlyGovernor initializer { + super._initialize(_rewardTokenAddresses, _assets, _pTokens); } /** diff --git a/contracts/contracts/strategies/MorphoCompoundStrategy.sol b/contracts/contracts/strategies/MorphoCompoundStrategy.sol index b3ead788e0..46a87ed906 100644 --- a/contracts/contracts/strategies/MorphoCompoundStrategy.sol +++ b/contracts/contracts/strategies/MorphoCompoundStrategy.sol @@ -7,8 +7,7 @@ pragma solidity ^0.8.0; * @author Origin Protocol Inc */ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { BaseCompoundStrategy } from "./BaseCompoundStrategy.sol"; -import { IERC20 } from "../utils/InitializableAbstractStrategy.sol"; +import { IERC20, BaseCompoundStrategy, InitializableAbstractStrategy } from "./BaseCompoundStrategy.sol"; import { IMorpho } from "../interfaces/morpho/IMorpho.sol"; import { ILens } from "../interfaces/morpho/ILens.sol"; import { StableMath } from "../utils/StableMath.sol"; @@ -20,26 +19,22 @@ contract MorphoCompoundStrategy is BaseCompoundStrategy { using SafeERC20 for IERC20; using StableMath for uint256; + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /** * @dev Initialize function, to set up initial internal state - * @param _vaultAddress Address of the Vault * @param _rewardTokenAddresses Address of reward token for platform * @param _assets Addresses of initial supported assets * @param _pTokens Platform Token corresponding addresses */ function initialize( - address _vaultAddress, address[] calldata _rewardTokenAddresses, address[] calldata _assets, address[] calldata _pTokens - ) external onlyGovernor initializer { - super._initialize( - MORPHO, - _vaultAddress, - _rewardTokenAddresses, - _assets, - _pTokens - ); + ) external override onlyGovernor initializer { + super._initialize(_rewardTokenAddresses, _assets, _pTokens); } /** diff --git a/contracts/contracts/strategies/ThreePoolStrategy.sol b/contracts/contracts/strategies/ThreePoolStrategy.sol index fa00b5a4eb..39e36d19ac 100644 --- a/contracts/contracts/strategies/ThreePoolStrategy.sol +++ b/contracts/contracts/strategies/ThreePoolStrategy.sol @@ -11,7 +11,7 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s import { ICurveGauge } from "./ICurveGauge.sol"; import { ICurvePool } from "./ICurvePool.sol"; import { ICRVMinter } from "./ICRVMinter.sol"; -import { IERC20, BaseCurveStrategy } from "./BaseCurveStrategy.sol"; +import { IERC20, BaseCurveStrategy, InitializableAbstractStrategy } from "./BaseCurveStrategy.sol"; import { StableMath } from "../utils/StableMath.sol"; import { Helpers } from "../utils/Helpers.sol"; @@ -29,12 +29,14 @@ contract ThreePoolStrategy is BaseCurveStrategy { address internal crvGaugeAddress; address internal crvMinterAddress; + constructor(BaseStrategyConfig memory _stratConfig) + InitializableAbstractStrategy(_stratConfig) + {} + /** * Initializer for setting up strategy internal state. This overrides the * InitializableAbstractStrategy initializer as Curve strategies don't fit * well within that abstraction. - * @param _platformAddress Address of the Curve 3pool - * @param _vaultAddress Address of the vault * @param _rewardTokenAddress Address of CRV * @param _assets Addresses of supported assets. MUST be passed in the same * order as returned by coins on the pool contract, i.e. @@ -44,8 +46,6 @@ contract ThreePoolStrategy is BaseCurveStrategy { * @param _crvMinterAddress Address of the CRV minter for rewards */ function initialize( - address _platformAddress, // 3Pool address - address _vaultAddress, address[] calldata _rewardTokenAddress, // CRV address[] calldata _assets, address[] calldata _pTokens, @@ -58,13 +58,7 @@ contract ThreePoolStrategy is BaseCurveStrategy { crvGaugeAddress = _crvGaugeAddress; crvMinterAddress = _crvMinterAddress; pTokenAddress = _pTokens[0]; - super._initialize( - _platformAddress, - _vaultAddress, - _rewardTokenAddress, - _assets, - _pTokens - ); + super._initialize(_rewardTokenAddress, _assets, _pTokens); _approveBase(); } diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 15d93b2163..13fff9526c 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** @@ -5,63 +6,66 @@ pragma solidity ^0.8.0; * @author Origin Protocol Inc */ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { BaseAuraStrategy } from "./BaseAuraStrategy.sol"; +import { BaseAuraStrategy, BaseBalancerStrategy } from "./BaseAuraStrategy.sol"; import { IBalancerVault } from "../../interfaces/balancer/IBalancerVault.sol"; import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { IMetaStablePool } from "../../interfaces/balancer/IMetaStablePool.sol"; -import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; +import { IERC20, InitializableAbstractStrategy } from "../../utils/InitializableAbstractStrategy.sol"; import { StableMath } from "../../utils/StableMath.sol"; -import "hardhat/console.sol"; - contract BalancerMetaPoolStrategy is BaseAuraStrategy { using SafeERC20 for IERC20; using StableMath for uint256; - address internal immutable stETH = - 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; - address internal immutable wstETH = - 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; - address internal immutable frxETH = - 0x5E8422345238F34275888049021821E8E08CAa1f; - address internal immutable sfrxETH = - 0xac3E018457B222d93114458476f3E3416Abbe38F; - - function getRateProviderRate(address _asset) - internal - view + constructor( + BaseStrategyConfig memory _stratConfig, + BaseBalancerConfig memory _balancerConfig, + address _auraRewardPoolAddress + ) + InitializableAbstractStrategy(_stratConfig) + BaseBalancerStrategy(_balancerConfig) + BaseAuraStrategy(_auraRewardPoolAddress) + {} + + /** + * @notice Deposits an `_amount` of vault collateral assets + * from the this strategy contract to the Balancer pool. + * @param _asset Address of the Vault collateral asset + * @param _amount The amount of Vault collateral assets to deposit + */ + function deposit(address _asset, uint256 _amount) + external override - returns (uint256) + whenNotInVaultContext + onlyVault + nonReentrant { - IMetaStablePool pool = IMetaStablePool(platformAddress); - IRateProvider[] memory providers = pool.getRateProviders(); - - uint256 providersLength = providers.length; - for (uint256 i = 0; i < providersLength; ++i) { - // _assets and corresponding rate providers are all in the same order - if (poolAssetsMapped[i] == _asset) { - // rate provider doesn't exist, defaults to 1e18 - if (address(providers[i]) == address(0)) { - return 1e18; - } - return providers[i].getRate(); - } - } + address[] memory assets = new address[](1); + uint256[] memory amounts = new uint256[](1); + assets[0] = _asset; + amounts[0] = _amount; - // should never happen - require(false, "Can not find rateProvider"); + _deposit(assets, amounts); } - function deposit(address _asset, uint256 _amount) + /** + * @notice Deposits specified vault collateral assets + * from the this strategy contract to the Balancer pool. + * @param _assets Address of the Vault collateral assets + * @param _amounts The amount of each asset to deposit + */ + function deposit(address[] memory _assets, uint256[] memory _amounts) external - override whenNotInVaultContext onlyVault nonReentrant { - _deposit(_asset, _amount); + _deposit(_assets, _amounts); } + /** + * @notice Deposits all supported assets in this strategy contract to the Balancer pool. + */ function depositAll() external override @@ -70,66 +74,76 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { nonReentrant { uint256 assetsLength = assetsMapped.length; + address[] memory assets = new address[](assetsLength); + uint256[] memory amounts = new uint256[](assetsLength); + + // For each vault collateral asset for (uint256 i = 0; i < assetsLength; ++i) { - uint256 balance = IERC20(assetsMapped[i]).balanceOf(address(this)); - if (balance > 0) { - _deposit(assetsMapped[i], balance); - } + assets[i] = assetsMapped[i]; + // Get the asset balance in this strategy contract + amounts[i] = IERC20(assets[i]).balanceOf(address(this)); } + _deposit(assets, amounts); } - function _deposit(address _asset, uint256 _amount) internal { - /* dust rounding issues with stETH. When allocate is called it tries - * to deposit 1-2 wei of stETH and the deposit fails with BPT amount check. - * - * TODO: solve this (only a problem when it is a default strategy for stETH) - */ - if (_asset == stEth && _amount < 20) { - return; - } - - emit Deposit(_asset, pTokenAddress, _amount); - - (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); - + function _deposit(address[] memory _assets, uint256[] memory _amounts) + internal + { (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( balancerPoolId ); - // TODO: refactor this bit and withdrawal bit to create amounts for in/out array - uint256 tokensLength = tokens.length; - uint256[] memory maxAmountsIn = new uint256[](tokensLength); - uint256 assetIndex = 0; - for (uint256 i = 0; i < tokensLength; ++i) { - if (address(tokens[i]) == poolAsset) { - maxAmountsIn[i] = poolAmount; - assetIndex = i; - } else { - maxAmountsIn[i] = 0; + uint256[] memory mappedAmounts = new uint256[](tokens.length); + address[] memory mappedAssets = new address[](tokens.length); + for (uint256 i = 0; i < _assets.length; ++i) { + address asset = _assets[i]; + uint256 amount = _amounts[i]; + mappedAssets[i] = toPoolAsset(_assets[i]); + + if (amount > 0) { + emit Deposit(asset, platformAddress, amount); + + // wrap rebasing assets like stETH and frxETH to wstETH and sfrxETH + (, mappedAmounts[i]) = wrapPoolAsset(asset, amount); } } - wrapPoolAsset(_asset, _amount); + // TODO move this loop into the previous loop + uint256[] memory amountsIn = new uint256[](tokens.length); + address[] memory poolAssets = new address[](tokens.length); + for (uint256 i = 0; i < tokens.length; ++i) { + // Convert IERC20 type to address + poolAssets[i] = address(tokens[i]); + + // For each of the mapped assets + for (uint256 j = 0; j < mappedAssets.length; ++j) { + // If the pool asset is the same as the mapped asset + if (poolAssets[i] == mappedAssets[j]) { + amountsIn[i] = mappedAmounts[j]; + } + } + } - uint256 minBPT = getBPTExpected(_asset, _amount); + uint256 minBPT = getBPTExpected(_assets, _amounts); uint256 minBPTwSlippage = minBPT.mulTruncate(1e18 - maxDepositSlippage); - /* TOKEN_IN_FOR_EXACT_BPT_OUT: - * User sends an estimated but unknown (computed at run time) quantity of a single token, - * and receives a precise quantity of BPT. + /* EXACT_TOKENS_IN_FOR_BPT_OUT: + * User sends precise quantities of tokens, and receives an + * estimated but unknown (computed at run time) quantity of BPT. * - * ['uint256', 'uint256', 'uint256'] - * [TOKEN_IN_FOR_EXACT_BPT_OUT, bptAmountOut, enterTokenIndex] + * ['uint256', 'uint256[]', 'uint256'] + * [EXACT_TOKENS_IN_FOR_BPT_OUT, amountsIn, minimumBPT] */ bytes memory userData = abi.encode( - IBalancerVault.WeightedPoolJoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT, - minBPTwSlippage, - assetIndex + IBalancerVault.WeightedPoolJoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, + amountsIn, + minBPTwSlippage ); IBalancerVault.JoinPoolRequest memory request = IBalancerVault - .JoinPoolRequest(poolAssetsMapped, maxAmountsIn, userData, false); + .JoinPoolRequest(poolAssets, amountsIn, userData, false); + // Add the pool assets in this strategy to the balancer pool balancerVault.joinPool( balancerPoolId, address(this), @@ -137,52 +151,123 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { request ); + // Deposit the Balancer Pool Tokens (BPT) into Aura _lpDepositAll(); } + /** + * @notice Withdraw a Vault collateral asset from the Balancer pool. + * @param _recipient Address to receive the Vault collateral assets. Typically is the Vault. + * @param _asset Address of the Vault collateral asset + * @param _amount The amount of Vault collateral assets to withdraw + */ function withdraw( address _recipient, address _asset, uint256 _amount ) external override whenNotInVaultContext onlyVault nonReentrant { - (address poolAsset, uint256 poolAmount) = toPoolAsset(_asset, _amount); + address[] memory assets = new address[](1); + uint256[] memory amounts = new uint256[](1); + assets[0] = _asset; + amounts[0] = _amount; + + _withdraw(_recipient, assets, amounts); + } + + /** + * @notice Withdraw multiple Vault collateral asset from the Balancer pool. + * @param _recipient Address to receive the Vault collateral assets. Typically is the Vault. + * @param _assets Addresses of the Vault collateral assets + * @param _amounts The amounts of Vault collateral assets to withdraw + */ + function withdraw( + address _recipient, + address[] memory _assets, + uint256[] memory _amounts + ) external whenNotInVaultContext onlyVault nonReentrant { + _withdraw(_recipient, _assets, _amounts); + } - uint256 BPTtoWithdraw = getBPTExpected(_asset, _amount); - // adjust for slippage - BPTtoWithdraw = BPTtoWithdraw.mulTruncate(1e18 + maxWithdrawalSlippage); + /** + * @dev Withdraw multiple Vault collateral asset from the Balancer pool. + * @param _recipient Address to receive the Vault collateral assets. Typically is the Vault. + * @param _assets Addresses of the Vault collateral assets + * @param _amounts The amounts of Vault collateral assets to withdraw + */ + function _withdraw( + address _recipient, + address[] memory _assets, + uint256[] memory _amounts + ) internal { + require(_assets.length == _amounts.length, "Invalid input arrays"); + + // STEP 1 - Calculate the max about of Balancer Pool Tokens (BPT) to withdraw + + // Estimate the required amount of Balancer Pool Tokens (BPT) for the assets + uint256 maxBPTtoWithdraw = getBPTExpected(_assets, _amounts); + // Increase BPTs by the max allowed slippage + // Any excess BPTs will be left in this strategy contract + maxBPTtoWithdraw = maxBPTtoWithdraw.mulTruncate( + 1e18 + maxWithdrawalSlippage + ); - _lpWithdraw(BPTtoWithdraw); + // STEP 2 - Withdraw the Balancer Pool Tokens (BPT) from Aura to this strategy contract + // Withdraw BPT from Aura allowing for BPTs left in this strategy contract from previous withdrawals + _lpWithdraw( + maxBPTtoWithdraw - IERC20(platformAddress).balanceOf(address(this)) + ); + + // STEP 3 - Calculate the Balancer pool assets and amounts from the vault collateral assets + + // Get all the supported balancer pool assets (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( balancerPoolId ); - uint256 tokensLength = tokens.length; - uint256[] memory minAmountsOut = new uint256[](tokensLength); - uint256 assetIndex = 0; - for (uint256 i = 0; i < tokensLength; ++i) { - if (address(tokens[i]) == poolAsset) { - minAmountsOut[i] = poolAmount; - assetIndex = i; - } else { - minAmountsOut[i] = 0; + // Calculate the balancer pool assets and amounts to withdraw + uint256[] memory poolAmountsOut = new uint256[](tokens.length); + address[] memory poolAssets = new address[](tokens.length); + // Is the wrapped asset amount indexed by the assets array, not the order of the Balancer pool tokens + // eg wstETH and sfrxETH amounts, not the stETH and frxETH amounts + uint256[] memory wrappedAssetAmounts = new uint256[](_assets.length); + + // For each of the Balancer pool assets + for (uint256 i = 0; i < tokens.length; ++i) { + poolAssets[i] = address(tokens[i]); + + // for each of the vault assets + for (uint256 j = 0; j < _assets.length; ++j) { + // Convert the Balancer pool asset back to a vault collateral asset + address vaultAsset = fromPoolAsset(poolAssets[i]); + + // If the vault asset equals the vault asset mapped from the Balancer pool asset + if (_assets[j] == vaultAsset) { + (, poolAmountsOut[i]) = toPoolAsset( + vaultAsset, + _amounts[j] + ); + wrappedAssetAmounts[j] = poolAmountsOut[i]; + } } } - /* Single asset exit: EXACT_BPT_IN_FOR_ONE_TOKEN_OUT: - * User sends a precise quantity of BPT, and receives an estimated but unknown - * (computed at run time) quantity of a single token + // STEP 4 - Withdraw the balancer pool assets from the pool + + /* Custom asset exit: BPT_IN_FOR_EXACT_TOKENS_OUT: + * User sends an estimated but unknown (computed at run time) quantity of BPT, + * and receives precise quantities of specified tokens. * - * ['uint256', 'uint256', 'uint256'] - * [EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, bptAmountIn, exitTokenIndex] + * ['uint256', 'uint256[]', 'uint256'] + * [BPT_IN_FOR_EXACT_TOKENS_OUT, amountsOut, maxBPTAmountIn] */ bytes memory userData = abi.encode( - IBalancerVault.WeightedPoolExitKind.EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, - BPTtoWithdraw, - assetIndex + IBalancerVault.WeightedPoolExitKind.BPT_IN_FOR_EXACT_TOKENS_OUT, + poolAmountsOut, + maxBPTtoWithdraw ); IBalancerVault.ExitPoolRequest memory request = IBalancerVault - .ExitPoolRequest(poolAssetsMapped, minAmountsOut, userData, false); + .ExitPoolRequest(poolAssets, poolAmountsOut, userData, false); balancerVault.exitPool( balancerPoolId, @@ -193,10 +278,34 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { request ); - unwrapPoolAsset(_asset, poolAmount); - IERC20(_asset).safeTransfer(_recipient, _amount); + // STEP 5 - Unswap balancer pool assets to vault collateral assets and sent to the vault. + + // For each of the specified assets + for (uint256 i = 0; i < _assets.length; ++i) { + // Unwrap assets like wstETH and sfrxETH to rebasing assets stETH and frxETH + uint256 assetAmount = 0; + if (wrappedAssetAmounts[i] > 0) { + assetAmount = unwrapPoolAsset( + _assets[i], + wrappedAssetAmounts[i] + ); + } + + // Transfer the vault collateral assets to the recipient, which is typically the vault + if (_amounts[i] > 0) { + IERC20(_assets[i]).safeTransfer(_recipient, _amounts[i]); + + emit Withdrawal(_assets[i], platformAddress, _amounts[i]); + } + } } + /** + * @notice Withdraws all supported Vault collateral assets from the Balancer pool + * and send to the OToken's Vault. + * + * Is only executable by the OToken's Vault or the Governor. + */ function withdrawAll() external override @@ -204,31 +313,37 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { onlyVaultOrGovernor nonReentrant { + // STEP 1 - Withdraw all Balancer Pool Tokens (BPT) from Aura to this strategy contract + _lpWithdrawAll(); + // STEP 2 - Calculate the minumum amount of pool assets to accept for the BPTs + + // Get the BPTs withdrawn from Aura plus any that were already in this strategy contract uint256 BPTtoWithdraw = IERC20(platformAddress).balanceOf( address(this) ); + // Get the balancer pool assets and their total balances (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault .getPoolTokens(balancerPoolId); - uint256 yourPoolShare = BPTtoWithdraw.divPrecisely( - IERC20(pTokenAddress).totalSupply() + // the strategy's share of the pool assets + uint256 strategyShare = BPTtoWithdraw.divPrecisely( + IERC20(platformAddress).totalSupply() ); - uint256 assetsMappedLength = balances.length; - uint256[] memory minAmountsOut = new uint256[](assetsMappedLength); - for (uint256 i = 0; i < assetsMappedLength; ++i) { - (address poolAsset, ) = toPoolAsset(assetsMapped[i], 0); - - if (address(tokens[i]) == poolAsset) { - minAmountsOut[i] = balances[i] - .mulTruncate(yourPoolShare) - .mulTruncate(1e18 - maxWithdrawalSlippage); - } + uint256[] memory minAmountsOut = new uint256[](tokens.length); + address[] memory poolAssets = new address[](tokens.length); + for (uint256 i = 0; i < tokens.length; ++i) { + poolAssets[i] = address(tokens[i]); + minAmountsOut[i] = balances[i] + .mulTruncate(strategyShare) + .mulTruncate(1e18 - maxWithdrawalSlippage); } + // STEP 3 - Withdraw the Balancer pool assets from the pool + /* Proportional exit: EXACT_BPT_IN_FOR_TOKENS_OUT: * User sends a precise quantity of BPT, and receives an estimated but unknown * (computed at run time) quantity of a single token @@ -242,7 +357,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { ); IBalancerVault.ExitPoolRequest memory request = IBalancerVault - .ExitPoolRequest(poolAssetsMapped, minAmountsOut, userData, false); + .ExitPoolRequest(poolAssets, minAmountsOut, userData, false); balancerVault.exitPool( balancerPoolId, @@ -253,48 +368,73 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { request ); - for (uint256 i = 0; i < assetsMappedLength; ++i) { - address asset = assetsMapped[i]; - (address poolAsset, ) = toPoolAsset(assetsMapped[i], 0); - unwrapPoolAsset(asset, IERC20(poolAsset).balanceOf(address(this))); + // STEP 4 - Convert the balancer pool assets to the vault collateral assets and send to the vault + + // For each of the Balancer pool assets + for (uint256 i = 0; i < tokens.length; ++i) { + address poolAsset = address(tokens[i]); + // Convert the balancer pool asset to the vault collateral asset + address asset = fromPoolAsset(poolAsset); + // Get the balancer pool assets withdraw from the pool plus any that were already in this strategy contract + uint256 poolAssetAmount = IERC20(poolAsset).balanceOf( + address(this) + ); + + // Unwrap assets like wstETH and sfrxETH to rebasing assets stETH and frxETH + uint256 assetAmount = 0; + if (poolAssetAmount > 0) { + assetAmount = unwrapPoolAsset(asset, poolAssetAmount); + } - uint256 transferAmount = IERC20(asset).balanceOf(address(this)); - IERC20(asset).safeTransfer(vaultAddress, transferAmount); - emit Withdrawal(asset, pTokenAddress, transferAmount); + // Transfer the vault collateral assets to the vault + if (assetAmount > 0) { + IERC20(asset).safeTransfer(vaultAddress, assetAmount); + emit Withdrawal(asset, platformAddress, assetAmount); + } } } + /** + * @notice Approves the Balancer pool to transfer all supported + * assets from this strategy. + * Also approve any suppered assets that are wrapped in the Balancer pool + * like stETH and frxETH, to be transferred from this strategy to their + * respective wrapper contracts. eg wstETH and sfrxETH. + * + * Is only executable by the Governor. + */ function safeApproveAllTokens() external override onlyGovernor nonReentrant { - for (uint256 i = 0; i < assetsMapped.length; i++) { + uint256 assetCount = assetsMapped.length; + for (uint256 i = 0; i < assetCount; ++i) { _approveAsset(assetsMapped[i]); } _approveBase(); } - // solhint-disable-next-line no-unused-vars - function _abstractSetPToken(address _asset, address _pToken) - internal - override - { - (address poolAsset, ) = toPoolAsset(_asset, 0); - // stEth + // solhin t-disable-next-line no-unused-vars + function _abstractSetPToken(address _asset, address) internal override { + address poolAsset = toPoolAsset(_asset); if (_asset == stETH) { - IERC20(stETH).approve(wstETH, 1e50); - // if frxEth + IERC20(stETH).safeApprove(wstETH, 1e50); } else if (_asset == frxETH) { - IERC20(frxETH).approve(sfrxETH, 1e50); + IERC20(frxETH).safeApprove(sfrxETH, 1e50); } _approveAsset(poolAsset); } + /** + * @dev Approves the Balancer Vault to transfer an asset from + * this strategy. The assets could be a Vault collateral asset + * like WETH or rETH; or a Balancer pool asset that wraps the vault asset + * like wstETH or sfrxETH. + */ function _approveAsset(address _asset) internal { IERC20 asset = IERC20(_asset); - // 3Pool for asset (required for adding liquidity) asset.safeApprove(address(balancerVault), 0); asset.safeApprove(address(balancerVault), type(uint256).max); } diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 8738bf1cfc..a2e2115ef7 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -7,30 +7,24 @@ pragma solidity ^0.8.0; */ import { BaseBalancerStrategy } from "./BaseBalancerStrategy.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol"; import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; import { StableMath } from "../../utils/StableMath.sol"; import { IRewardStaking } from "../IRewardStaking.sol"; -import "hardhat/console.sol"; - abstract contract BaseAuraStrategy is BaseBalancerStrategy { using SafeERC20 for IERC20; using StableMath for uint256; - address internal auraRewardPoolAddress; - address internal auraRewardStakerAddress; - uint256 internal auraDepositorPTokenId; + /// @notice Address of the Aura rewards pool + address public immutable auraRewardPoolAddress; + // renamed from __reserved to not shadow BaseBalancerStrategy.__reserved, int256[50] private __reserved_2; - struct InitConfig { - address platformAddress; // platformAddress Address of the Balancer's pool - address vaultAddress; // vaultAddress Address of the vault - address auraRewardPoolAddress; // auraRewardPoolAddress Address of the Aura rewards pool - address auraRewardStakerAddress; // auraRewardStakerAddress Address of the Aura rewards staker - uint256 auraDepositorPTokenId; // auraDepositorPTokenId Address of the Aura rewards staker - bytes32 balancerPoolId; // balancerPoolId bytes32 poolId + constructor(address _auraRewardPoolAddress) { + auraRewardPoolAddress = _auraRewardPoolAddress; } /** @@ -42,51 +36,47 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { * order as returned by coins on the pool contract, i.e. * WETH, stETH * @param _pTokens Platform Token corresponding addresses - * @param initConfig additional configuration */ function initialize( address[] calldata _rewardTokenAddresses, // BAL & AURA address[] calldata _assets, - address[] calldata _pTokens, - InitConfig calldata initConfig - ) external onlyGovernor initializer { - auraRewardPoolAddress = initConfig.auraRewardPoolAddress; - auraRewardStakerAddress = initConfig.auraRewardStakerAddress; - auraDepositorPTokenId = initConfig.auraDepositorPTokenId; - pTokenAddress = _pTokens[0]; + address[] calldata _pTokens + ) external override onlyGovernor initializer { maxWithdrawalSlippage = 1e15; maxDepositSlippage = 1e15; - balancerPoolId = initConfig.balancerPoolId; + IERC20[] memory poolAssets = getPoolAssets(); - uint256 assetsLength = _assets.length; require( - poolAssets.length == assetsLength, - "Pool assets and _assets should be the same length." + poolAssets.length == _assets.length, + "Pool assets length mismatch" ); - for (uint256 i = 0; i < assetsLength; ++i) { + for (uint256 i = 0; i < _assets.length; ++i) { (address asset, ) = fromPoolAsset(address(poolAssets[i]), 0); - require( - _assets[i] == asset, - "Pool assets and _assets should all have the same numerical order." - ); - poolAssetsMapped.push(address(poolAssets[i])); + require(_assets[i] == asset, "Pool assets mismatch"); } - super._initialize( - initConfig.platformAddress, - initConfig.vaultAddress, - _rewardTokenAddresses, - _assets, - _pTokens - ); + super._initialize(_rewardTokenAddresses, _assets, _pTokens); _approveBase(); } + /** + * @dev Deposit all Balancer Pool Tokens (BPT) in this strategy contract + * to the Aura rewards pool. + */ function _lpDepositAll() internal virtual override { uint256 bptBalance = IERC20(platformAddress).balanceOf(address(this)); - IERC4626(auraRewardPoolAddress).deposit(bptBalance, address(this)); + uint256 auraLp = IERC4626(auraRewardPoolAddress).deposit( + bptBalance, + address(this) + ); + require(bptBalance == auraLp, "Aura LP != BPT"); } + /** + * @dev Withdraw `numBPTTokens` Balancer Pool Tokens (BPT) from + * the Aura rewards pool to this strategy contract. + * @param numBPTTokens Number of Balancer Pool Tokens (BPT) to withdraw + */ function _lpWithdraw(uint256 numBPTTokens) internal virtual override { IRewardStaking(auraRewardPoolAddress).withdrawAndUnwrap( numBPTTokens, @@ -94,6 +84,10 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { ); } + /** + * @dev Withdraw all Balancer Pool Tokens (BPT) from + * the Aura rewards pool to this strategy contract. + */ function _lpWithdrawAll() internal virtual override { uint256 bptBalance = IERC4626(auraRewardPoolAddress).balanceOf( address(this) @@ -105,6 +99,9 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { ); } + /** + * @notice Collects BAL and AURA tokens from the rewards pool. + */ function collectRewardTokens() external virtual @@ -112,47 +109,27 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { onlyHarvester nonReentrant { - // Collect CRV and CVX + // Collect BAL and AURA IRewardStaking(auraRewardPoolAddress).getReward(); _collectRewardTokens(); } - function checkBalance(address _asset) - external + /// @notice Balancer Pool Tokens (BPT) in the Balancer pool and the Aura rewards pool. + function _getBalancerPoolTokens() + internal view - virtual override - returns (uint256) + returns (uint256 balancerPoolTokens) { - (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault - .getPoolTokens(balancerPoolId); - // pool balance + aura balance - uint256 bptBalance = IERC20(pTokenAddress).balanceOf(address(this)) + + balancerPoolTokens = + IERC20(platformAddress).balanceOf(address(this)) + IERC4626(auraRewardPoolAddress).balanceOf(address(this)); - - // yourPoolShare denominated in 1e18. (1e18 == 100%) - uint256 yourPoolShare = bptBalance.divPrecisely( - IERC20(pTokenAddress).totalSupply() - ); - - uint256 balancesLength = balances.length; - for (uint256 i = 0; i < balancesLength; ++i) { - (address poolAsset, ) = toPoolAsset(_asset, 0); - if (address(tokens[i]) == poolAsset) { - (, uint256 assetAmount) = fromPoolAsset( - poolAsset, - balances[i].mulTruncate(yourPoolShare) - ); - return assetAmount; - } - } } function _approveBase() internal virtual override { super._approveBase(); - IERC20 pToken = IERC20(pTokenAddress); - // Gauge for LP token + IERC20 pToken = IERC20(platformAddress); pToken.safeApprove(auraRewardPoolAddress, 0); pToken.safeApprove(auraRewardPoolAddress, type(uint256).max); } diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index f9efaa2b83..5b5fc13930 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -12,35 +12,43 @@ import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { VaultReentrancyLib } from "./VaultReentrancyLib.sol"; import { IOracle } from "../../interfaces/IOracle.sol"; import { IVault } from "../../interfaces/IVault.sol"; +import { IRETH } from "../../interfaces/IRETH.sol"; import { IWstETH } from "../../interfaces/IWstETH.sol"; import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; import { StableMath } from "../../utils/StableMath.sol"; -import "hardhat/console.sol"; abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { using SafeERC20 for IERC20; using StableMath for uint256; - IBalancerVault internal immutable balancerVault = - IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); - address internal immutable stEth = - 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; - address internal immutable wstEth = - 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; - address internal immutable frxEth = - 0x5E8422345238F34275888049021821E8E08CAa1f; - address internal immutable sfrxEth = - 0xac3E018457B222d93114458476f3E3416Abbe38F; - - address internal pTokenAddress; - bytes32 internal balancerPoolId; - // Full list of all assets as they are present in the Balancer pool - address[] internal poolAssetsMapped; + + address public immutable rETH; + address public immutable stETH; + address public immutable wstETH; + address public immutable frxETH; + address public immutable sfrxETH; + + /// @notice Address of the Balancer vault + IBalancerVault public immutable balancerVault; + /// @notice Balancer pool identifier + bytes32 public immutable balancerPoolId; + // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) uint256 public maxWithdrawalSlippage; // Max deposit slippage denominated in 1e18 (1e18 == 100%) uint256 public maxDepositSlippage; + int256[50] private __reserved; + struct BaseBalancerConfig { + address rEthAddress; // Address of the rETH token + address stEthAddress; // Address of the stETH token + address wstEthAddress; // Address of the wstETH token + address frxEthAddress; // Address of the frxEth token + address sfrxEthAddress; // Address of the sfrxEth token + address balancerVaultAddress; // Address of the Balancer vault + bytes32 balancerPoolId; // Balancer pool identifier + } + event MaxWithdrawalSlippageUpdated( uint256 _prevMaxSlippagePercentage, uint256 _newMaxSlippagePercentage @@ -50,6 +58,17 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256 _newMaxSlippagePercentage ); + constructor(BaseBalancerConfig memory _balancerConfig) { + rETH = _balancerConfig.rEthAddress; + stETH = _balancerConfig.stEthAddress; + wstETH = _balancerConfig.wstEthAddress; + frxETH = _balancerConfig.frxEthAddress; + sfrxETH = _balancerConfig.sfrxEthAddress; + + balancerVault = IBalancerVault(_balancerConfig.balancerVaultAddress); + balancerPoolId = _balancerConfig.balancerPoolId; + } + /** * @dev Ensure we are not in a Vault context when this function is called, by attempting a no-op internal * balance operation. If we are already in a Vault transaction (e.g., a swap, join, or exit), the Vault's @@ -64,7 +83,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } /** - * @dev Returns bool indicating whether asset is supported by strategy + * @notice Returns bool indicating whether asset is supported by strategy * @param _asset Address of the asset */ function supportsAsset(address _asset) @@ -76,63 +95,100 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { return assetToPToken[_asset] != address(0); } + /** + * @notice Get strategy's share of an assets in the Balancer pool. + * This is not the value (OSUD or ETH) of the assets in the Balancer pool. + * @param _asset Address of the Vault collateral asset + * @return amount the amount of vault collateral assets + */ function checkBalance(address _asset) external view virtual override - returns (uint256) + returns (uint256 amount) { + // Get the total balance of each of the Balancer pool assets (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault .getPoolTokens(balancerPoolId); - // yourPoolShare denominated in 1e18. (1e18 == 100%) - uint256 yourPoolShare = IERC20(pTokenAddress) - .balanceOf(address(this)) - .divPrecisely(IERC20(pTokenAddress).totalSupply()); - - uint256 balancesLength = balances.length; - for (uint256 i = 0; i < balancesLength; ++i) { - (address poolAsset, ) = toPoolAsset(_asset, 0); + // The strategy's shares of the assets in the Balancer pool + // denominated in 1e18. (1e18 == 100%) + uint256 strategyShare = _getBalancerPoolTokens().divPrecisely( + IERC20(platformAddress).totalSupply() + ); + for (uint256 i = 0; i < balances.length; ++i) { + address poolAsset = toPoolAsset(_asset); if (address(tokens[i]) == poolAsset) { - (, uint256 assetAmount) = fromPoolAsset( + // convert Balancer pool asset amount to Vault asset amount. + // eg wstETH -> stETH or sfrxETH -> frxETH + (, amount) = fromPoolAsset( poolAsset, - balances[i].mulTruncate(yourPoolShare) + balances[i].mulTruncate(strategyShare) ); - return assetAmount; + return amount; } } } + /** + * @notice Returns the value of all assets managed by this strategy. + * Uses the Balancer pool's rate (virtual price) to convert the strategy's + * Balancer Pool Tokens (BPT) to ETH value. + * @return value The ETH value + */ + function checkBalance() external view virtual returns (uint256 value) { + uint256 bptBalance = _getBalancerPoolTokens(); + + // Convert BPT to ETH value + value = bptBalance.mulTruncate( + IRateProvider(platformAddress).getRate() + ); + } + + /// @notice Balancer Pool Tokens (BPT) in the Balancer pool. + function _getBalancerPoolTokens() + internal + view + virtual + returns (uint256 balancerPoolTokens) + { + balancerPoolTokens = IERC20(platformAddress).balanceOf(address(this)); + } + + /* solhint-disable max-line-length */ + /** + * @notice BPT price is calculated by dividing the pool (sometimes wrapped) market price by the + * rateProviderRate of that asset. To get BPT expected we need to multiply that by underlying + * asset amount divided by BPT token rate. BPT token rate is similar to Curve's virtual_price + * and expresses how much has the price of BPT appreciated in relation to the underlying assets. + * + * @dev + * bptPrice = pool_asset_oracle_price / pool_asset_rate + * + * Since we only have oracle prices for the unwrapped version of the assets the equation + * turns into: + * + * bptPrice = from_pool_token(asset_amount).amount * oracle_price / pool_asset_rate + * + * bptExpected = bptPrice(in relation to specified asset) * asset_amount / BPT_token_rate + * + * and since from_pool_token(asset_amount).amount and pool_asset_rate cancel each-other out + * this makes the final equation: + * + * bptExpected = oracle_price * asset_amount / BPT_token_rate + * + * more explanation here: + * https://www.notion.so/originprotocol/Support-Balancer-OETH-strategy-9becdea132704e588782a919d7d471eb?pvs=4#382834f9815e46a7937f3acca0f637c5 + */ + /* solhint-enable max-line-length */ function getBPTExpected(address _asset, uint256 _amount) internal view virtual returns (uint256 bptExpected) { - /* BPT price is calculated by dividing the pool (sometimes wrapped) market price by the - * rateProviderRate of that asset. To get BPT expected we need to multiply that by underlying - * asset amount divided by BPT token rate. BPT token rate is similar to Curve's virtual_price - * and expresses how much has the price of BPT appreciated in relation to the underlying assets. - * - * bptPrice = pool_asset_oracle_price / pool_asset_rate - * - * Since we only have oracle prices for the unwrapped version of the assets the equation - * turns into: - * - * bptPrice = from_pool_token(asset_amount).amount * oracle_price / pool_asset_rate - * - * bptExpected = bptPrice(in relation to specified asset) * asset_amount / BPT_token_rate - * - * and since from_pool_token(asset_amount).amount and pool_asset_rate cancel each-other out - * this makes the final equation: - * - * bptExpected = oracle_price * asset_amount / BPT_token_rate - * - * more explanation here: - * https://www.notion.so/originprotocol/Support-Balancer-OETH-strategy-9becdea132704e588782a919d7d471eb?pvs=4#382834f9815e46a7937f3acca0f637c5 - */ address priceProvider = IVault(vaultAddress).priceProvider(); uint256 strategyAssetMarketPrice = IOracle(priceProvider).price(_asset); uint256 bptRate = IRateProvider(platformAddress).getRate(); @@ -142,11 +198,29 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { .divPrecisely(bptRate); } - function getRateProviderRate(address _asset) + function getBPTExpected(address[] memory _assets, uint256[] memory _amounts) internal view virtual - returns (uint256); + returns (uint256 bptExpected) + { + // Get the oracle from the OETH Vault + address priceProvider = IVault(vaultAddress).priceProvider(); + + for (uint256 i = 0; i < _assets.length; ++i) { + uint256 strategyAssetMarketPrice = IOracle(priceProvider).price( + _assets[i] + ); + // convert asset amount to ETH amount + bptExpected = + bptExpected + + _amounts[i].mulTruncate(strategyAssetMarketPrice); + } + + uint256 bptRate = IRateProvider(platformAddress).getRate(); + // Convert ETH amount to BPT amount + bptExpected = bptExpected.divPrecisely(bptRate); + } function _lpDepositAll() internal virtual; @@ -155,18 +229,15 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { function _lpWithdrawAll() internal virtual; /** - * Balancer returns assets and rateProviders for corresponding assets ordered + * @notice Balancer returns assets and rateProviders for corresponding assets ordered * by numerical order. */ function getPoolAssets() internal view returns (IERC20[] memory assets) { - (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( - balancerPoolId - ); - return tokens; + (assets, , ) = balancerVault.getPoolTokens(balancerPoolId); } /** - * If an asset is rebasing the Balancer pools have a wrapped versions of assets + * @dev If an asset is rebasing the Balancer pools have a wrapped versions of assets * that the strategy supports. This function converts the pool(wrapped) asset * and corresponding amount to strategy asset. */ @@ -176,19 +247,15 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { returns (address poolAsset, uint256 poolAmount) { poolAmount = 0; - // if stEth - if (asset == stEth) { - // wstEth - poolAsset = wstEth; + if (asset == stETH) { + poolAsset = wstETH; if (amount > 0) { - poolAmount = IWstETH(wstEth).getWstETHByStETH(amount); + poolAmount = IWstETH(wstETH).getWstETHByStETH(amount); } - // if frxEth - } else if (asset == frxEth) { - // sfrxEth - poolAsset = sfrxEth; + } else if (asset == frxETH) { + poolAsset = sfrxETH; if (amount > 0) { - poolAmount = IERC4626(sfrxEth).convertToShares(amount); + poolAmount = IERC4626(sfrxETH).convertToShares(amount); } } else { poolAsset = asset; @@ -197,36 +264,54 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } /** - * Converts rebasing asset to its wrapped counterpart. + * @dev Converts a Vault collateral asset to a Balancer pool asset. + * stETH becomes wstETH, frxETH becomes sfrxETH and everything else stays the same. + * @param asset Address of the Vault collateral asset. + * @return Address of the Balancer pool asset. + */ + function toPoolAsset(address asset) internal view returns (address) { + if (asset == stETH) { + return wstETH; + } else if (asset == frxETH) { + return sfrxETH; + } + return asset; + } + + /** + * @dev Converts rebasing asset to its wrapped counterpart. */ function wrapPoolAsset(address asset, uint256 amount) internal - returns (uint256 wrappedAmount) + returns (address wrappedAsset, uint256 wrappedAmount) { - // if stEth - if (asset == stEth) { - wrappedAmount = IWstETH(wstEth).wrap(amount); - // if frxEth - } else if (asset == frxEth) { - wrappedAmount = IERC4626(sfrxEth).deposit(amount, address(this)); + if (asset == stETH) { + wrappedAsset = wstETH; + if (amount > 0) { + wrappedAmount = IWstETH(wstETH).wrap(amount); + } + } else if (asset == frxETH) { + wrappedAsset = sfrxETH; + if (amount > 0) { + wrappedAmount = IERC4626(sfrxETH).deposit(amount, address(this)); + } } else { + wrappedAsset = asset; wrappedAmount = amount; } } /** - * Converts wrapped asset to its rebasing counterpart. + * @dev Converts wrapped asset to its rebasing counterpart. */ function unwrapPoolAsset(address asset, uint256 amount) internal returns (uint256 wrappedAmount) { - // if stEth - if (asset == stEth) { - wrappedAmount = IWstETH(wstEth).unwrap(amount); - // if frxEth - } else if (asset == frxEth) { - wrappedAmount = IERC4626(sfrxEth).withdraw( + if (asset == stETH) { + wrappedAmount = IWstETH(wstETH).unwrap(amount); + } else if (asset == frxETH) { + wrappedAmount = IERC4626(sfrxETH).withdraw( amount, address(this), address(this) @@ -237,7 +322,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } /** - * If an asset is rebasing the Balancer pools have a wrapped versions of assets + * @dev If an asset is rebasing the Balancer pools have a wrapped versions of assets * that the strategy supports. This function converts the rebasing strategy asset * and corresponding amount to wrapped(pool) asset. */ @@ -247,19 +332,15 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { returns (address asset, uint256 amount) { amount = 0; - // if wstEth - if (poolAsset == wstEth) { - // stEth - asset = stEth; + if (poolAsset == wstETH) { + asset = stETH; if (poolAmount > 0) { - amount = IWstETH(wstEth).getStETHByWstETH(poolAmount); + amount = IWstETH(wstETH).getStETHByWstETH(poolAmount); } - // if frxEth - } else if (poolAsset == sfrxEth) { - // sfrxEth - asset = frxEth; + } else if (poolAsset == sfrxETH) { + asset = frxETH; if (poolAmount > 0) { - amount = IERC4626(sfrxEth).convertToAssets(poolAmount); + amount = IERC4626(sfrxETH).convertToAssets(poolAmount); } } else { asset = poolAsset; @@ -267,8 +348,22 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } } + function fromPoolAsset(address poolAsset) + internal + view + returns (address asset) + { + if (poolAsset == wstETH) { + asset = stETH; + } else if (poolAsset == sfrxETH) { + asset = frxETH; + } else { + asset = poolAsset; + } + } + /** - * @dev Sets max withdrawal slippage that is considered when removing + * @notice Sets max withdrawal slippage that is considered when removing * liquidity from Balancer pools. * @param _maxWithdrawalSlippage Max withdrawal slippage denominated in * wad (number with 18 decimals): 1e18 == 100%, 1e16 == 1% @@ -293,7 +388,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } /** - * @dev Sets max deposit slippage that is considered when adding + * @notice Sets max deposit slippage that is considered when adding * liquidity to Balancer pools. * @param _maxDepositSlippage Max deposit slippage denominated in * wad (number with 18 decimals): 1e18 == 100%, 1e16 == 1% @@ -315,7 +410,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } function _approveBase() internal virtual { - IERC20 pToken = IERC20(pTokenAddress); + IERC20 pToken = IERC20(platformAddress); // Balancer vault for BPT token (required for removing liquidity) pToken.safeApprove(address(balancerVault), 0); pToken.safeApprove(address(balancerVault), type(uint256).max); diff --git a/contracts/contracts/strategies/balancer/README.md b/contracts/contracts/strategies/balancer/README.md new file mode 100644 index 0000000000..8e5aa3468e --- /dev/null +++ b/contracts/contracts/strategies/balancer/README.md @@ -0,0 +1,15 @@ +# Diagrams + +## Balancer Metapool Strategy + +### Hierarchy + +![Balancer Metapool Strategy Hierarchy](../../../docs/BalancerMetaPoolStrategyHierarchy.svg) + +### Squashed + +![Balancer Metapool Strategy Squashed](../../../docs/BalancerMetaPoolStrategySquashed.svg) + +### Storage + +![Balancer Metapool Strategy Storage](../../../docs/BalancerMetaPoolStrategyStorage.svg) diff --git a/contracts/contracts/utils/BalancerErrors.sol b/contracts/contracts/utils/BalancerErrors.sol index b9355b0a1a..0d3f2d591f 100644 --- a/contracts/contracts/utils/BalancerErrors.sol +++ b/contracts/contracts/utils/BalancerErrors.sol @@ -12,7 +12,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity >=0.7.1 <0.9.0; +pragma solidity >=0.7.4 <0.9.0; // solhint-disable diff --git a/contracts/contracts/utils/Initializable.sol b/contracts/contracts/utils/Initializable.sol index 0e7d9e32e3..9a47d79211 100644 --- a/contracts/contracts/utils/Initializable.sol +++ b/contracts/contracts/utils/Initializable.sol @@ -1,6 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +/** + * @title Base contract any contracts that need to initialize state after deployment. + * @author Origin Protocol Inc + */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. diff --git a/contracts/contracts/utils/InitializableAbstractStrategy.sol b/contracts/contracts/utils/InitializableAbstractStrategy.sol index 9606d2ded7..59bc175b21 100644 --- a/contracts/contracts/utils/InitializableAbstractStrategy.sol +++ b/contracts/contracts/utils/InitializableAbstractStrategy.sol @@ -1,6 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +/** + * @title Base contract for vault strategies. + * @author Origin Protocol Inc + */ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -29,30 +33,39 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { address _newHarvesterAddress ); - // Core address for the given platform - address public platformAddress; + /// @notice Address of the underlying platform + address public immutable platformAddress; + /// @notice Address of the OToken vault + address public immutable vaultAddress; - address public vaultAddress; + /// @dev Replaced with an immutable variable + // slither-disable-next-line constable-states + address private _deprecated_platformAddress; + + /// @dev Replaced with an immutable + // slither-disable-next-line constable-states + address private _deprecated_vaultAddress; - // asset => pToken (Platform Specific Token Address) + /// @notice asset => pToken (Platform Specific Token Address) mapping(address => address) public assetToPToken; - // Full list of all assets supported here + /// @notice Full list of all assets supported by the strategy address[] internal assetsMapped; // Deprecated: Reward token address // slither-disable-next-line constable-states - address public _deprecated_rewardTokenAddress; + address private _deprecated_rewardTokenAddress; // Deprecated: now resides in Harvester's rewardTokenConfigs // slither-disable-next-line constable-states - uint256 public _deprecated_rewardLiquidationThreshold; + uint256 private _deprecated_rewardLiquidationThreshold; - // Address of the one address allowed to collect reward tokens + /// @notice Address of the Harvester contract allowed to collect reward tokens address public harvesterAddress; - // Reward token addresses + /// @notice Address of the reward tokens. eg CRV, BAL, CVX, AURA address[] public rewardTokenAddresses; + /* Reserved for future expansion. Used to be 100 storage slots * and has decreased to accommodate: * - harvesterAddress @@ -60,24 +73,31 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { */ int256[98] private _reserved; + struct BaseStrategyConfig { + address platformAddress; // Address of the underlying platform + address vaultAddress; // Address of the OToken's Vault + } + + /** + * @param _config The platform and OToken vault addresses + */ + constructor(BaseStrategyConfig memory _config) { + platformAddress = _config.platformAddress; + vaultAddress = _config.vaultAddress; + } + /** - * @dev Internal initialize function, to set up initial internal state - * @param _platformAddress Generic platform address - * @param _vaultAddress Address of the Vault + * @notice Internal initialize function, to set up initial internal state * @param _rewardTokenAddresses Address of reward token for platform * @param _assets Addresses of initial supported assets * @param _pTokens Platform Token corresponding addresses */ function initialize( - address _platformAddress, - address _vaultAddress, address[] calldata _rewardTokenAddresses, address[] calldata _assets, address[] calldata _pTokens - ) external onlyGovernor initializer { + ) external virtual onlyGovernor initializer { InitializableAbstractStrategy._initialize( - _platformAddress, - _vaultAddress, _rewardTokenAddresses, _assets, _pTokens @@ -85,40 +105,38 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { } function _initialize( - address _platformAddress, - address _vaultAddress, address[] calldata _rewardTokenAddresses, address[] memory _assets, address[] memory _pTokens ) internal { - platformAddress = _platformAddress; - vaultAddress = _vaultAddress; rewardTokenAddresses = _rewardTokenAddresses; uint256 assetCount = _assets.length; require(assetCount == _pTokens.length, "Invalid input arrays"); - for (uint256 i = 0; i < assetCount; i++) { + for (uint256 i = 0; i < assetCount; ++i) { _setPTokenAddress(_assets[i], _pTokens[i]); } } /** - * @dev Collect accumulated reward token and send to Vault. + * @notice Collect accumulated reward token and send to Vault. */ function collectRewardTokens() external virtual onlyHarvester nonReentrant { _collectRewardTokens(); } function _collectRewardTokens() internal { - for (uint256 i = 0; i < rewardTokenAddresses.length; i++) { + uint256 rewardTokenCount = rewardTokenAddresses.length; + for (uint256 i = 0; i < rewardTokenCount; ++i) { IERC20 rewardToken = IERC20(rewardTokenAddresses[i]); uint256 balance = rewardToken.balanceOf(address(this)); + address harvesterAddr = harvesterAddress; emit RewardTokenCollected( - harvesterAddress, - rewardTokenAddresses[i], + harvesterAddr, + address(rewardToken), balance ); - rewardToken.safeTransfer(harvesterAddress, balance); + rewardToken.safeTransfer(harvesterAddr, balance); } } @@ -163,8 +181,8 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { } /** - * @dev Set the reward token addresses. - * @param _rewardTokenAddresses Address array of the reward token + * @notice Set the reward token addresses. Any old addresses will be overwritten. + * @param _rewardTokenAddresses Array of reward token addresses */ function setRewardTokenAddresses(address[] calldata _rewardTokenAddresses) external @@ -185,7 +203,7 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { } /** - * @dev Get the reward token addresses. + * @notice Get the reward token addresses. * @return address[] the reward token addresses. */ function getRewardTokenAddresses() @@ -197,7 +215,7 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { } /** - * @dev Provide support for asset by passing its pToken address. + * @notice Provide support for asset by passing its pToken address. * This method can only be called by the system Governor * @param _asset Address for the asset * @param _pToken Address for the corresponding platform token @@ -210,7 +228,7 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { } /** - * @dev Remove a supported asset by passing its index. + * @notice Remove a supported asset by passing its index. * This method can only be called by the system Governor * @param _assetIndex Index of the asset to be removed */ @@ -229,7 +247,7 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { } /** - * @dev Provide support for asset by passing its pToken address. + * @notice Provide support for asset by passing its pToken address. * Add to internal mappings and execute the platform specific, * abstract method `_abstractSetPToken` * @param _asset Address for the asset @@ -251,7 +269,7 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { } /** - * @dev Transfer token to governor. Intended for recovering tokens stuck in + * @notice Transfer token to governor. Intended for recovering tokens stuck in * strategy contracts, i.e. mistaken sends. * @param _asset Address for the asset * @param _amount Amount of the asset to transfer @@ -264,8 +282,8 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { } /** - * @dev Set the reward token addresses. - * @param _harvesterAddress Address of the harvester + * @notice Set the Harvester contract that can collect rewards. + * @param _harvesterAddress Address of the harvester contract. */ function setHarvesterAddress(address _harvesterAddress) external @@ -286,19 +304,20 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { function safeApproveAllTokens() external virtual; /** - * @dev Deposit an amount of asset into the platform + * @notice Deposit an amount of assets into the platform * @param _asset Address for the asset * @param _amount Units of asset to deposit */ function deposit(address _asset, uint256 _amount) external virtual; /** - * @dev Deposit balance of all supported assets into the platform + * @notice Deposit all supported assets in this strategy contract to the platform */ function depositAll() external virtual; /** - * @dev Withdraw an amount of asset from the platform. + * @notice Withdraw an `amount` of assets from the platform and + * send to the `_recipient`. * @param _recipient Address to which the asset should be sent * @param _asset Address of the asset * @param _amount Units of asset to withdraw @@ -310,12 +329,13 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { ) external virtual; /** - * @dev Withdraw all assets from strategy sending assets to Vault. + * @notice Withdraw all supported assets from platform and + * sends to the OToken's Vault. */ function withdrawAll() external virtual; /** - * @dev Get the total asset value held in the platform. + * @notice Get the total asset value held in the platform. * This includes any interest that was generated since depositing. * @param _asset Address of the asset * @return balance Total value of the asset in the platform @@ -327,7 +347,7 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { returns (uint256 balance); /** - * @dev Check if an asset is supported. + * @notice Check if an asset is supported. * @param _asset Address of the asset * @return bool Whether asset is supported */ diff --git a/contracts/contracts/utils/InitializableERC20Detailed.sol b/contracts/contracts/utils/InitializableERC20Detailed.sol index 70c0a819e3..05a831cc80 100644 --- a/contracts/contracts/utils/InitializableERC20Detailed.sol +++ b/contracts/contracts/utils/InitializableERC20Detailed.sol @@ -6,6 +6,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @dev Optional functions from the ERC20 standard. * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol + * @author Origin Protocol Inc */ abstract contract InitializableERC20Detailed is IERC20 { // Storage gap to skip storage from prior to OUSD reset @@ -32,14 +33,14 @@ abstract contract InitializableERC20Detailed is IERC20 { } /** - * @dev Returns the name of the token. + * @notice Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** - * @dev Returns the symbol of the token, usually a shorter version of the + * @notice Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { @@ -47,7 +48,7 @@ abstract contract InitializableERC20Detailed is IERC20 { } /** - * @dev Returns the number of decimals used to get its user representation. + * @notice Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * diff --git a/contracts/deploy/000_mock.js b/contracts/deploy/000_mock.js index db93afa717..4be0d40cc9 100644 --- a/contracts/deploy/000_mock.js +++ b/contracts/deploy/000_mock.js @@ -17,11 +17,6 @@ const { bytecode: MANAGER_BYTECODE, } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json"); -const { - abi: TOKEN_DESCRIPTOR_ABI, - bytecode: TOKEN_DESCRIPTOR_BYTECODE, -} = require("@uniswap/v3-periphery/artifacts/contracts/NonfungibleTokenPositionDescriptor.sol/NonfungibleTokenPositionDescriptor.json"); - const { abi: QUOTER_ABI, bytecode: QUOTER_BYTECODE, diff --git a/contracts/deploy/001_core.js b/contracts/deploy/001_core.js index a50e76741a..6570462974 100644 --- a/contracts/deploy/001_core.js +++ b/contracts/deploy/001_core.js @@ -37,7 +37,9 @@ const deployAaveStrategy = async () => { "InitializeGovernedUpgradeabilityProxy" ); const cAaveStrategyProxy = await ethers.getContract("AaveStrategyProxy"); - const dAaveStrategy = await deployWithConfirmation("AaveStrategy"); + const dAaveStrategy = await deployWithConfirmation("AaveStrategy", [ + [assetAddresses.AAVE_ADDRESS_PROVIDER, cVaultProxy.address], + ]); const cAaveStrategy = await ethers.getContractAt( "AaveStrategy", dAaveStrategyProxy.address @@ -56,13 +58,11 @@ const deployAaveStrategy = async () => { log("Initialized AaveStrategyProxy"); const initFunctionName = - "initialize(address,address,address[],address[],address[],address,address)"; + "initialize(address[],address[],address[],address,address)"; await withConfirmation( cAaveStrategy .connect(sDeployer) [initFunctionName]( - assetAddresses.AAVE_ADDRESS_PROVIDER, - cVaultProxy.address, [assetAddresses.AAVE_TOKEN], [assetAddresses.DAI], [assetAddresses.aDAI], @@ -111,7 +111,9 @@ const deployCompoundStrategy = async () => { const cCompoundStrategyProxy = await ethers.getContract( "CompoundStrategyProxy" ); - const dCompoundStrategy = await deployWithConfirmation("CompoundStrategy"); + const dCompoundStrategy = await deployWithConfirmation("CompoundStrategy", [ + [addresses.dead, cVaultProxy.address], + ]); const cCompoundStrategy = await ethers.getContractAt( "CompoundStrategy", dCompoundStrategyProxy.address @@ -128,8 +130,6 @@ const deployCompoundStrategy = async () => { cCompoundStrategy .connect(sDeployer) .initialize( - addresses.dead, - cVaultProxy.address, [assetAddresses.COMP], [assetAddresses.DAI], [assetAddresses.cDAI] @@ -166,12 +166,17 @@ const deployThreePoolStrategy = async () => { const sDeployer = await ethers.provider.getSigner(deployerAddr); const sGovernor = await ethers.provider.getSigner(governorAddr); + // Initialize Strategies + const cVaultProxy = await ethers.getContract("VaultProxy"); + await deployWithConfirmation("ThreePoolStrategyProxy"); const cThreePoolStrategyProxy = await ethers.getContract( "ThreePoolStrategyProxy" ); - const dThreePoolStrategy = await deployWithConfirmation("ThreePoolStrategy"); + const dThreePoolStrategy = await deployWithConfirmation("ThreePoolStrategy", [ + [assetAddresses.ThreePool, cVaultProxy.address], + ]); const cThreePoolStrategy = await ethers.getContractAt( "ThreePoolStrategy", cThreePoolStrategyProxy.address @@ -186,16 +191,10 @@ const deployThreePoolStrategy = async () => { ); log("Initialized ThreePoolStrategyProxy"); - // Initialize Strategies - const cVaultProxy = await ethers.getContract("VaultProxy"); await withConfirmation( cThreePoolStrategy .connect(sDeployer) - [ - "initialize(address,address,address[],address[],address[],address,address)" - ]( - assetAddresses.ThreePool, - cVaultProxy.address, + ["initialize(address[],address[],address[],address,address)"]( [assetAddresses.CRV], [assetAddresses.DAI, assetAddresses.USDC, assetAddresses.USDT], [ @@ -238,10 +237,14 @@ const deployConvexStrategy = async () => { const sDeployer = await ethers.provider.getSigner(deployerAddr); const sGovernor = await ethers.provider.getSigner(governorAddr); + const cVaultProxy = await ethers.getContract("VaultProxy"); + await deployWithConfirmation("ConvexStrategyProxy"); const cConvexStrategyProxy = await ethers.getContract("ConvexStrategyProxy"); - const dConvexStrategy = await deployWithConfirmation("ConvexStrategy"); + const dConvexStrategy = await deployWithConfirmation("ConvexStrategy", [ + [assetAddresses.ThreePool, cVaultProxy.address], + ]); const cConvexStrategy = await ethers.getContractAt( "ConvexStrategy", cConvexStrategyProxy.address @@ -257,17 +260,12 @@ const deployConvexStrategy = async () => { log("Initialized ConvexStrategyProxy"); // Initialize Strategies - const cVaultProxy = await ethers.getContract("VaultProxy"); const mockBooster = await ethers.getContract("MockBooster"); const mockRewardPool = await ethers.getContract("MockRewardPool"); await withConfirmation( cConvexStrategy .connect(sDeployer) - [ - "initialize(address,address,address[],address[],address[],address,address,uint256)" - ]( - assetAddresses.ThreePool, - cVaultProxy.address, + ["initialize(address[],address[],address[],address,address,uint256)"]( [assetAddresses.CRV, assetAddresses.CVX], [assetAddresses.DAI, assetAddresses.USDC, assetAddresses.USDT], [ @@ -310,13 +308,16 @@ const deployConvexLUSDMetaStrategy = async () => { const sDeployer = await ethers.provider.getSigner(deployerAddr); const sGovernor = await ethers.provider.getSigner(governorAddr); + const cVaultProxy = await ethers.getContract("VaultProxy"); + await deployWithConfirmation("ConvexLUSDMetaStrategyProxy"); const cConvexLUSDMetaStrategyProxy = await ethers.getContract( "ConvexLUSDMetaStrategyProxy" ); const dConvexLUSDMetaStrategy = await deployWithConfirmation( - "ConvexGeneralizedMetaStrategy" + "ConvexGeneralizedMetaStrategy", + [[assetAddresses.ThreePool, cVaultProxy.address]] ); const cConvexLUSDMetaStrategy = await ethers.getContractAt( "ConvexGeneralizedMetaStrategy", @@ -333,7 +334,6 @@ const deployConvexLUSDMetaStrategy = async () => { log("Initialized ConvexLUSDMetaStrategyProxy"); // Initialize Strategies - const cVaultProxy = await ethers.getContract("VaultProxy"); const mockBooster = await ethers.getContract("MockBooster"); const mockRewardPool = await ethers.getContract("MockRewardPool"); @@ -342,7 +342,7 @@ const deployConvexLUSDMetaStrategy = async () => { cConvexLUSDMetaStrategy .connect(sDeployer) [ - "initialize(address[],address[],address[],(address,address,address,address,address,address,address,uint256))" + "initialize(address[],address[],address[],(address,address,address,address,address,uint256))" ]( [assetAddresses.CVX, assetAddresses.CRV], [assetAddresses.DAI, assetAddresses.USDC, assetAddresses.USDT], @@ -352,8 +352,6 @@ const deployConvexLUSDMetaStrategy = async () => { assetAddresses.ThreePoolToken, ], [ - assetAddresses.ThreePool, - cVaultProxy.address, mockBooster.address, // _cvxDepositorAddress, assetAddresses.ThreePoolLUSDMetapool, // metapool address, LUSD.address, // LUSD @@ -393,13 +391,16 @@ const deployConvexOUSDMetaStrategy = async () => { const sDeployer = await ethers.provider.getSigner(deployerAddr); const sGovernor = await ethers.provider.getSigner(governorAddr); + const cVaultProxy = await ethers.getContract("VaultProxy"); + await deployWithConfirmation("ConvexOUSDMetaStrategyProxy"); const cConvexOUSDMetaStrategyProxy = await ethers.getContract( "ConvexOUSDMetaStrategyProxy" ); const dConvexOUSDMetaStrategy = await deployWithConfirmation( - "ConvexOUSDMetaStrategy" + "ConvexOUSDMetaStrategy", + [[assetAddresses.ThreePool, cVaultProxy.address]] ); const cConvexOUSDMetaStrategy = await ethers.getContractAt( "ConvexOUSDMetaStrategy", @@ -416,7 +417,6 @@ const deployConvexOUSDMetaStrategy = async () => { log("Initialized ConvexOUSDMetaStrategyProxy"); // Initialize Strategies - const cVaultProxy = await ethers.getContract("VaultProxy"); const mockBooster = await ethers.getContract("MockBooster"); const mockRewardPool = await ethers.getContract("MockRewardPool"); const ousd = await ethers.getContract("OUSDProxy"); @@ -425,7 +425,7 @@ const deployConvexOUSDMetaStrategy = async () => { cConvexOUSDMetaStrategy .connect(sDeployer) [ - "initialize(address[],address[],address[],(address,address,address,address,address,address,address,uint256))" + "initialize(address[],address[],address[],(address,address,address,address,address,uint256))" ]( [assetAddresses.CVX, assetAddresses.CRV], [assetAddresses.DAI, assetAddresses.USDC, assetAddresses.USDT], @@ -435,8 +435,6 @@ const deployConvexOUSDMetaStrategy = async () => { assetAddresses.ThreePoolToken, ], [ - assetAddresses.ThreePool, - cVaultProxy.address, mockBooster.address, // _cvxDepositorAddress, assetAddresses.ThreePoolOUSDMetapool, // metapool address, ousd.address, // _ousdAddress, @@ -766,7 +764,9 @@ const deployFraxEthStrategy = async () => { const cFraxETHStrategyProxy = await ethers.getContract( "FraxETHStrategyProxy" ); - const dFraxETHStrategy = await deployWithConfirmation("FraxETHStrategy"); + const dFraxETHStrategy = await deployWithConfirmation("FraxETHStrategy", [ + [assetAddresses.sfrxETH, cOETHVaultProxy.address], + ]); const cFraxETHStrategy = await ethers.getContractAt( "FraxETHStrategy", dFraxETHStrategyProxy.address @@ -782,13 +782,7 @@ const deployFraxEthStrategy = async () => { await withConfirmation( cFraxETHStrategy .connect(sDeployer) - .initialize( - assetAddresses.sfrxETH, - cOETHVaultProxy.address, - [], - [assetAddresses.frxETH], - [assetAddresses.sfrxETH] - ) + .initialize([], [assetAddresses.frxETH], [assetAddresses.sfrxETH]) ); log("Initialized FraxETHStrategy"); await withConfirmation( diff --git a/contracts/deploy/057_drip_all.js b/contracts/deploy/057_drip_all.js index c421401384..c812f4674d 100644 --- a/contracts/deploy/057_drip_all.js +++ b/contracts/deploy/057_drip_all.js @@ -1,6 +1,4 @@ const { deploymentWithGovernanceProposal } = require("../utils/deploy"); -const addresses = require("../utils/addresses"); -const { isMainnet } = require("../test/helpers.js"); module.exports = deploymentWithGovernanceProposal( { @@ -9,31 +7,22 @@ module.exports = deploymentWithGovernanceProposal( onlyOnFork: true, // this is only executed in forked environment //proposalId: "40434364243407050666554191388123037800510237271029051418887027936281231737485" }, - async ({ - assetAddresses, - deployWithConfirmation, - ethers, - getTxOpts, - withConfirmation, - }) => { - const { deployerAddr, governorAddr } = await getNamedAccounts(); - const sDeployer = await ethers.provider.getSigner(deployerAddr); - + async ({ deployWithConfirmation, ethers }) => { // Current contracts const cVaultProxy = await ethers.getContract("VaultProxy"); // const cHarvester = await ethers.getContract("Harvester"); const dVaultCore = await deployWithConfirmation("VaultCore"); - const dVaultAdmin = await deployWithConfirmation("VaultAdmin"); + // const dVaultAdmin = await deployWithConfirmation("VaultAdmin"); - const cVaultCore = await ethers.getContract( - "VaultCore", - cVaultProxy.address - ); - const cVaultAdmin = await ethers.getContract( - "VaultAdmin", - cVaultProxy.address - ); + // const cVaultCore = await ethers.getContract( + // "VaultCore", + // cVaultProxy.address + // ); + // const cVaultAdmin = await ethers.getContract( + // "VaultAdmin", + // cVaultProxy.address + // ); // Governance Actions // ---------------- diff --git a/contracts/deploy/071_balancer_wstETH_WETH.js b/contracts/deploy/071_balancer_rETH_WETH.js similarity index 67% rename from contracts/deploy/071_balancer_wstETH_WETH.js rename to contracts/deploy/071_balancer_rETH_WETH.js index 609c0b87eb..8d1163238d 100644 --- a/contracts/deploy/071_balancer_wstETH_WETH.js +++ b/contracts/deploy/071_balancer_rETH_WETH.js @@ -1,24 +1,19 @@ const { deploymentWithGovernanceProposal } = require("../utils/deploy"); const addresses = require("../utils/addresses"); -const { BigNumber } = require("ethers"); -const { balancerWstEthWethPID } = require("../utils/constants"); +const { balancer_rETH_WETH_PID } = require("../utils/constants"); + +const platformAddress = addresses.mainnet.rETH_WETH_BPT; module.exports = deploymentWithGovernanceProposal( { - deployName: "071_balancer_wstETH_WETH", + deployName: "071_balancer_rETH_WETH", forceDeploy: false, //forceSkip: true, deployerIsProposer: true, //proposalId: , }, - async ({ - assetAddresses, - deployWithConfirmation, - ethers, - getTxOpts, - withConfirmation, - }) => { - const { deployerAddr, governorAddr } = await getNamedAccounts(); + async ({ deployWithConfirmation, ethers, getTxOpts, withConfirmation }) => { + const { deployerAddr } = await getNamedAccounts(); const sDeployer = await ethers.provider.getSigner(deployerAddr); // Current contracts @@ -27,27 +22,36 @@ module.exports = deploymentWithGovernanceProposal( "OETHVaultAdmin", cOETHVaultProxy.address ); - const cOETHVault = await ethers.getContractAt( - "OETHVault", - cOETHVaultProxy.address - ); // Deployer Actions // ---------------- - // 1. Deploy new proxy + // 1. Deploy new proxy for the Balancer strategy // New strategy will be living at a clean address const dOETHBalancerMetaPoolStrategyProxy = await deployWithConfirmation( - "OETHBalancerMetaPoolWstEthWethStrategyProxy" + "OETHBalancerMetaPoolrEthStrategyProxy" ); const cOETHBalancerMetaPoolStrategyProxy = await ethers.getContractAt( - "OETHBalancerMetaPoolWstEthWethStrategyProxy", + "OETHBalancerMetaPoolrEthStrategyProxy", dOETHBalancerMetaPoolStrategyProxy.address ); - // 2. Deploy new implementation + // 2. Deploy new Balancer strategy implementation const dOETHBalancerMetaPoolStrategyImpl = await deployWithConfirmation( - "BalancerMetaPoolStrategy" + "BalancerMetaPoolStrategy", + [ + [platformAddress, cOETHVaultProxy.address], + [ + addresses.mainnet.rETH, + addresses.mainnet.stETH, + addresses.mainnet.wstETH, + addresses.mainnet.frxETH, + addresses.mainnet.sfrxETH, + addresses.mainnet.balancerVault, // Address of the Balancer vault + balancer_rETH_WETH_PID, // Pool ID of the Balancer pool + ], + addresses.mainnet.rETH_WETH_AuraRewards, // Address of the Aura rewards contract + ] ); const cOETHBalancerMetaPoolStrategy = await ethers.getContractAt( "BalancerMetaPoolStrategy", @@ -61,30 +65,21 @@ module.exports = deploymentWithGovernanceProposal( ); // 3. Encode the init data - const initFunction = - "initialize(address[],address[],address[],(address,address,address,address,uint256,bytes32))"; + const initFunction = "initialize(address[],address[],address[])"; const initData = cOETHBalancerMetaPoolStrategy.interface.encodeFunctionData( initFunction, [ [addresses.mainnet.BAL, addresses.mainnet.AURA], - [addresses.mainnet.stETH, addresses.mainnet.WETH], - [addresses.mainnet.wstETH_WETH_BPT, addresses.mainnet.wstETH_WETH_BPT], - [ - addresses.mainnet.wstETH_WETH_BPT, - cOETHVaultProxy.address, - addresses.mainnet.auraRewardPool, - addresses.mainnet.CurveOUSDMetaPool, // auraRewardStakerAddress - balancerWstEthWethPID, // auraDepositorPTokenId - "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080", - ], + [addresses.mainnet.rETH, addresses.mainnet.WETH], + [platformAddress, platformAddress], ] ); // 4. Init the proxy to point at the implementation + // prettier-ignore await withConfirmation( cOETHBalancerMetaPoolStrategyProxy - .connect(sDeployer) - ["initialize(address,address,bytes)"]( + .connect(sDeployer)["initialize(address,address,bytes)"]( dOETHBalancerMetaPoolStrategyImpl.address, addresses.mainnet.Timelock, initData, diff --git a/contracts/docs/AaveStrategyHierarchy.svg b/contracts/docs/AaveStrategyHierarchy.svg index f075e23abe..ab28c359ed 100644 --- a/contracts/docs/AaveStrategyHierarchy.svg +++ b/contracts/docs/AaveStrategyHierarchy.svg @@ -4,148 +4,218 @@ - - + + UmlClassDiagram - + 7 - -Governable -../contracts/governance/Governable.sol + +Governable +../contracts/governance/Governable.sol - + -35 +40 <<Interface>> IVault ../contracts/interfaces/IVault.sol - + + +180 + +VaultStorage +../contracts/vault/VaultStorage.sol + + + +40->180 + + + + -109 +124 AaveStrategy ../contracts/strategies/AaveStrategy.sol - + -121 +137 <<Interface>> IAaveLendingPool ../contracts/strategies/IAave.sol - - -109->121 + + +124->137 - + -122 +138 <<Interface>> ILendingPoolAddressesProvider ../contracts/strategies/IAave.sol - - -109->122 + + +124->138 - + -123 +139 <<Interface>> IAaveIncentivesController ../contracts/strategies/IAaveIncentivesController.sol - - -109->123 + + +124->139 - + -124 +140 <<Interface>> IAaveStakedToken ../contracts/strategies/IAaveStakeToken.sol - - -109->124 + + +124->140 - - -150 + + +168 <<Abstract>> InitializableAbstractStrategy ../contracts/utils/InitializableAbstractStrategy.sol - - -109->150 + + +124->168 - + -149 - -<<Abstract>> -Initializable -../contracts/utils/Initializable.sol +159 + +OUSD +../contracts/token/OUSD.sol - - -150->7 - - + + +159->7 + + - - -150->35 + + +167 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol + + + +159->167 + + + + + +170 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol + + + +159->170 + + + + + +168->7 + + + + + +168->40 - - -150->149 - - - - - -150->150 - + + +168->167 + + + + + +168->168 + - - -436 - -<<Interface>> -IERC20 -../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - - - -150->436 - - + + +357 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + + +168->357 + + + + + +170->357 + + + + + +180->7 + + + + + +180->159 + + + + + +180->167 + + diff --git a/contracts/docs/AaveStrategySquashed.svg b/contracts/docs/AaveStrategySquashed.svg index 36a2873ca9..e7e064544d 100644 --- a/contracts/docs/AaveStrategySquashed.svg +++ b/contracts/docs/AaveStrategySquashed.svg @@ -4,93 +4,96 @@ - - + + UmlClassDiagram - - + + -109 - -AaveStrategy -../contracts/strategies/AaveStrategy.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _reserved: int256[98] <<InitializableAbstractStrategy>> -Internal: -   assetsMapped: address[] <<InitializableAbstractStrategy>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   platformAddress: address <<InitializableAbstractStrategy>> -   vaultAddress: address <<InitializableAbstractStrategy>> -   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> -   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> -   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> -   harvesterAddress: address <<InitializableAbstractStrategy>> -   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>> -   referralCode: uint16 <<AaveStrategy>> -   incentivesController: IAaveIncentivesController <<AaveStrategy>> -   stkAave: IAaveStakedToken <<AaveStrategy>> - -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> -    _collectRewardTokens() <<InitializableAbstractStrategy>> -    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    _abstractSetPToken(_asset: address, _aToken: address) <<AaveStrategy>> -    _deposit(_asset: address, _amount: uint256) <<AaveStrategy>> -    _getATokenFor(_asset: address): address <<AaveStrategy>> -    _getLendingPool(): IAaveLendingPool <<AaveStrategy>> -External: -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> -    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<AaveStrategy>> -    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> -    setPTokenAddress(_asset: address, _pToken: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    safeApproveAllTokens() <<onlyGovernor, nonReentrant>> <<AaveStrategy>> -    deposit(_asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<AaveStrategy>> -    depositAll() <<onlyVault, nonReentrant>> <<AaveStrategy>> -    withdraw(_recipient: address, _asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<AaveStrategy>> -    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<AaveStrategy>> -    checkBalance(_asset: address): (balance: uint256) <<AaveStrategy>> -    supportsAsset(_asset: address): bool <<AaveStrategy>> -    initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[], _incentivesAddress: address, _stkAaveAddress: address) <<onlyGovernor, initializer>> <<AaveStrategy>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> -    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> -    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> -    constructor() <<Governable>> -    governor(): address <<Governable>> -    isGovernor(): bool <<Governable>> +124 + +AaveStrategy +../contracts/strategies/AaveStrategy.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_platformAddress: address <<InitializableAbstractStrategy>> +   _deprecated_vaultAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +   _reserved: int256[98] <<InitializableAbstractStrategy>> +Internal: +   assetsMapped: address[] <<InitializableAbstractStrategy>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   platformAddress: address <<InitializableAbstractStrategy>> +   vaultAddress: address <<InitializableAbstractStrategy>> +   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> +   harvesterAddress: address <<InitializableAbstractStrategy>> +   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>> +   referralCode: uint16 <<AaveStrategy>> +   incentivesController: IAaveIncentivesController <<AaveStrategy>> +   stkAave: IAaveStakedToken <<AaveStrategy>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> +    _collectRewardTokens() <<InitializableAbstractStrategy>> +    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    _abstractSetPToken(_asset: address, _aToken: address) <<AaveStrategy>> +    _deposit(_asset: address, _amount: uint256) <<AaveStrategy>> +    _getATokenFor(_asset: address): address <<AaveStrategy>> +    _getLendingPool(): IAaveLendingPool <<AaveStrategy>> +External: +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> +    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<AaveStrategy>> +    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> +    setPTokenAddress(_asset: address, _pToken: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    safeApproveAllTokens() <<onlyGovernor, nonReentrant>> <<AaveStrategy>> +    deposit(_asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<AaveStrategy>> +    depositAll() <<onlyVault, nonReentrant>> <<AaveStrategy>> +    withdraw(_recipient: address, _asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<AaveStrategy>> +    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<AaveStrategy>> +    checkBalance(_asset: address): (balance: uint256) <<AaveStrategy>> +    supportsAsset(_asset: address): bool <<AaveStrategy>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[], _incentivesAddress: address, _stkAaveAddress: address) <<onlyGovernor, initializer>> <<AaveStrategy>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> +    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> +    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_stratConfig: BaseStrategyConfig) <<AaveStrategy>>    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> diff --git a/contracts/docs/AaveStrategyStorage.svg b/contracts/docs/AaveStrategyStorage.svg index e9c22bc78b..699aec2198 100644 --- a/contracts/docs/AaveStrategyStorage.svg +++ b/contracts/docs/AaveStrategyStorage.svg @@ -53,13 +53,13 @@ uint256[50]: Initializable.______gap (1600) -unallocated (12) - -address: InitializableAbstractStrategy.platformAddress (20) +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_platformAddress (20) -unallocated (12) - -address: InitializableAbstractStrategy.vaultAddress (20) +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_vaultAddress (20) mapping(address=>address): InitializableAbstractStrategy.assetToPToken (32) diff --git a/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg b/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg new file mode 100644 index 0000000000..4ae82abd7d --- /dev/null +++ b/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg @@ -0,0 +1,329 @@ + + + + + + +UmlClassDiagram + + + +7 + +Governable +../contracts/governance/Governable.sol + + + +35 + +<<Interface>> +IOracle +../contracts/interfaces/IOracle.sol + + + +37 + +<<Interface>> +IRETH +../contracts/interfaces/IRETH.sol + + + +42 + +<<Interface>> +IVault +../contracts/interfaces/IVault.sol + + + +182 + +VaultStorage +../contracts/vault/VaultStorage.sol + + + +42->182 + + + + + +44 + +<<Interface>> +IWstETH +../contracts/interfaces/IWstETH.sol + + + +189 + +<<Interface>> +IBalancerVault +../contracts/interfaces/balancer/IBalancerVault.sol + + + +197 + +<<Interface>> +IRateProvider +../contracts/interfaces/balancer/IRateProvider.sol + + + +150 + +<<Interface>> +IRewardStaking +../contracts/strategies/IRewardStaking.sol + + + +229 + +BalancerMetaPoolStrategy +../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol + + + +229->189 + + + + + +230 + +<<Abstract>> +BaseAuraStrategy +../contracts/strategies/balancer/BaseAuraStrategy.sol + + + +229->230 + + + + + +230->150 + + + + + +231 + +<<Abstract>> +BaseBalancerStrategy +../contracts/strategies/balancer/BaseBalancerStrategy.sol + + + +230->231 + + + + + +234 + +<<Interface>> +IERC4626 +../lib/openzeppelin/interfaces/IERC4626.sol + + + +230->234 + + + + + +231->35 + + + + + +231->37 + + + + + +231->42 + + + + + +231->44 + + + + + +231->189 + + + + + +231->197 + + + + + +170 + +<<Abstract>> +InitializableAbstractStrategy +../contracts/utils/InitializableAbstractStrategy.sol + + + +231->170 + + + + + +161 + +OUSD +../contracts/token/OUSD.sol + + + +161->7 + + + + + +169 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol + + + +161->169 + + + + + +172 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol + + + +161->172 + + + + + +170->7 + + + + + +170->42 + + + + + +170->169 + + + + + +170->170 + + + + + +358 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + + +170->358 + + + + + +172->358 + + + + + +182->7 + + + + + +182->161 + + + + + +182->169 + + + + + +234->358 + + + + + +729 + +<<Interface>> +IERC20Metadata +../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol + + + +234->729 + + + + + +729->358 + + + + + diff --git a/contracts/docs/BalancerMetaPoolStrategySquashed.svg b/contracts/docs/BalancerMetaPoolStrategySquashed.svg new file mode 100644 index 0000000000..741d7a018c --- /dev/null +++ b/contracts/docs/BalancerMetaPoolStrategySquashed.svg @@ -0,0 +1,134 @@ + + + + + + +UmlClassDiagram + + + +229 + +BalancerMetaPoolStrategy +../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_platformAddress: address <<InitializableAbstractStrategy>> +   _deprecated_vaultAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +   _reserved: int256[98] <<InitializableAbstractStrategy>> +   __reserved: int256[50] <<BaseBalancerStrategy>> +   __reserved_2: int256[50] <<BaseAuraStrategy>> +Internal: +   assetsMapped: address[] <<InitializableAbstractStrategy>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   platformAddress: address <<InitializableAbstractStrategy>> +   vaultAddress: address <<InitializableAbstractStrategy>> +   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> +   harvesterAddress: address <<InitializableAbstractStrategy>> +   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>> +   rETH: address <<BaseBalancerStrategy>> +   stETH: address <<BaseBalancerStrategy>> +   wstETH: address <<BaseBalancerStrategy>> +   frxETH: address <<BaseBalancerStrategy>> +   sfrxETH: address <<BaseBalancerStrategy>> +   balancerVault: IBalancerVault <<BaseBalancerStrategy>> +   balancerPoolId: bytes32 <<BaseBalancerStrategy>> +   maxWithdrawalSlippage: uint256 <<BaseBalancerStrategy>> +   maxDepositSlippage: uint256 <<BaseBalancerStrategy>> +   auraRewardPoolAddress: address <<BaseAuraStrategy>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> +    _collectRewardTokens() <<InitializableAbstractStrategy>> +    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    _abstractSetPToken(_asset: address, address) <<BalancerMetaPoolStrategy>> +    _getBalancerPoolTokens(): (balancerPoolTokens: uint256) <<BaseAuraStrategy>> +    getBPTExpected(_asset: address, _amount: uint256): (bptExpected: uint256) <<BaseBalancerStrategy>> +    getBPTExpected(_assets: address[], _amounts: uint256[]): (bptExpected: uint256) <<BaseBalancerStrategy>> +    _lpDepositAll() <<BaseAuraStrategy>> +    _lpWithdraw(numBPTTokens: uint256) <<BaseAuraStrategy>> +    _lpWithdrawAll() <<BaseAuraStrategy>> +    getPoolAssets(): (assets: IERC20[]) <<BaseBalancerStrategy>> +    toPoolAsset(asset: address, amount: uint256): (poolAsset: address, poolAmount: uint256) <<BaseBalancerStrategy>> +    toPoolAsset(asset: address): address <<BaseBalancerStrategy>> +    wrapPoolAsset(asset: address, amount: uint256): (wrappedAsset: address, wrappedAmount: uint256) <<BaseBalancerStrategy>> +    previewUnwrapPoolAsset(asset: address, assetAmount: uint256): (wrappedAmount: uint256) <<BaseBalancerStrategy>> +    unwrapPoolAsset(asset: address, amount: uint256): (wrappedAmount: uint256) <<BaseBalancerStrategy>> +    fromPoolAsset(poolAsset: address, poolAmount: uint256): (asset: address, amount: uint256) <<BaseBalancerStrategy>> +    fromPoolAsset(poolAsset: address): (asset: address) <<BaseBalancerStrategy>> +    _approveBase() <<BaseAuraStrategy>> +    _deposit(_assets: address[], _amounts: uint256[]) <<BalancerMetaPoolStrategy>> +    _withdraw(_recipient: address, _assets: address[], _amounts: uint256[]) <<BalancerMetaPoolStrategy>> +    _approveAsset(_asset: address) <<BalancerMetaPoolStrategy>> +External: +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<BaseAuraStrategy>> +    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<BaseAuraStrategy>> +    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> +    setPTokenAddress(_asset: address, _pToken: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    safeApproveAllTokens() <<onlyGovernor, nonReentrant>> <<BalancerMetaPoolStrategy>> +    deposit(_asset: address, _amount: uint256) <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    depositAll() <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    withdraw(_recipient: address, _asset: address, _amount: uint256) <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    withdrawAll() <<whenNotInVaultContext, onlyVaultOrGovernor, nonReentrant>> <<BalancerMetaPoolStrategy>> +    checkBalance(_asset: address): (value: uint256) <<BaseBalancerStrategy>> +    supportsAsset(_asset: address): bool <<BaseBalancerStrategy>> +    checkBalance(): (value: uint256) <<BaseBalancerStrategy>> +    setMaxWithdrawalSlippage(_maxWithdrawalSlippage: uint256) <<onlyVaultOrGovernorOrStrategist>> <<BaseBalancerStrategy>> +    setMaxDepositSlippage(_maxDepositSlippage: uint256) <<onlyVaultOrGovernorOrStrategist>> <<BaseBalancerStrategy>> +    deposit(_assets: address[], _amounts: uint256[]) <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    withdraw(_recipient: address, _assets: address[], _amounts: uint256[]) <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> +    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> +    <<event>> MaxWithdrawalSlippageUpdated(_prevMaxSlippagePercentage: uint256, _newMaxSlippagePercentage: uint256) <<BaseBalancerStrategy>> +    <<event>> MaxDepositSlippageUpdated(_prevMaxSlippagePercentage: uint256, _newMaxSlippagePercentage: uint256) <<BaseBalancerStrategy>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> +    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> +    <<modifier>> whenNotInVaultContext() <<BaseBalancerStrategy>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_config: BaseStrategyConfig) <<InitializableAbstractStrategy>> +    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    constructor(_balancerConfig: BaseBalancerConfig) <<BaseBalancerStrategy>> +    constructor(_auraRewardPoolAddress: address) <<BaseAuraStrategy>> +    constructor(_stratConfig: BaseStrategyConfig, _balancerConfig: BaseBalancerConfig, _auraRewardPoolAddress: address) <<BalancerMetaPoolStrategy>> + + + diff --git a/contracts/docs/BalancerMetaPoolStrategyStorage.svg b/contracts/docs/BalancerMetaPoolStrategyStorage.svg new file mode 100644 index 0000000000..28380694dc --- /dev/null +++ b/contracts/docs/BalancerMetaPoolStrategyStorage.svg @@ -0,0 +1,285 @@ + + + + + + +StorageDiagram + + + +7 + +BalancerMetaPoolStrategy <<Contract>> + +slot + +0 + +1-50 + +51 + +52 + +53 + +54 + +55 + +56 + +57 + +58 + +59-156 + +157 + +158 + +159-208 + +209-258 + +type: <inherited contract>.variable (bytes) + +unallocated (30) + +bool: Initializable.initializing (1) + +bool: Initializable.initialized (1) + +uint256[50]: Initializable.______gap (1600) + +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_platformAddress (20) + +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_vaultAddress (20) + +mapping(address=>address): InitializableAbstractStrategy.assetToPToken (32) + +address[]: InitializableAbstractStrategy.assetsMapped (32) + +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_rewardTokenAddress (20) + +uint256: InitializableAbstractStrategy._deprecated_rewardLiquidationThreshold (32) + +unallocated (12) + +address: InitializableAbstractStrategy.harvesterAddress (20) + +address[]: InitializableAbstractStrategy.rewardTokenAddresses (32) + +int256[98]: InitializableAbstractStrategy._reserved (3136) + +uint256: BaseBalancerStrategy.maxWithdrawalSlippage (32) + +uint256: BaseBalancerStrategy.maxDepositSlippage (32) + +int256[50]: BaseBalancerStrategy.__reserved (1600) + +int256[50]: BaseAuraStrategy.__reserved_2 (1600) + + + +1 + +uint256[50]: ______gap <<Array>> + +slot + +1 + +2 + +3-48 + +49 + +50 + +type: variable (bytes) + +uint256 (32) + +uint256 (32) + +---- (1472) + +uint256 (32) + +uint256 (32) + + + +7:8->1 + + + + + +2 + +address[]: assetsMapped <<Array>> +0x4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b8 + +offset + +0 + +type: variable (bytes) + +unallocated (12) + +address (20) + + + +7:13->2 + + + + + +3 + +address[]: rewardTokenAddresses <<Array>> +0xa2999d817b6757290b50e8ecf3fa939673403dd35c97de392fdb343b4015ce9e + +offset + +0 + +type: variable (bytes) + +unallocated (12) + +address (20) + + + +7:18->3 + + + + + +4 + +int256[98]: _reserved <<Array>> + +slot + +59 + +60 + +61-154 + +155 + +156 + +type: variable (bytes) + +int256 (32) + +int256 (32) + +---- (3008) + +int256 (32) + +int256 (32) + + + +7:24->4 + + + + + +5 + +int256[50]: __reserved <<Array>> + +slot + +159 + +160 + +161-206 + +207 + +208 + +type: variable (bytes) + +int256 (32) + +int256 (32) + +---- (1472) + +int256 (32) + +int256 (32) + + + +7:32->5 + + + + + +6 + +int256[50]: __reserved_2 <<Array>> + +slot + +209 + +210 + +211-256 + +257 + +258 + +type: variable (bytes) + +int256 (32) + +int256 (32) + +---- (1472) + +int256 (32) + +int256 (32) + + + +7:38->6 + + + + + diff --git a/contracts/docs/CompStrategyHierarchy.svg b/contracts/docs/CompStrategyHierarchy.svg index b5fb24d399..ca83249a08 100644 --- a/contracts/docs/CompStrategyHierarchy.svg +++ b/contracts/docs/CompStrategyHierarchy.svg @@ -4,17 +4,17 @@ - - + + UmlClassDiagram - + 7 - -Governable -../contracts/governance/Governable.sol + +Governable +../contracts/governance/Governable.sol @@ -24,120 +24,190 @@ IComptroller ../contracts/interfaces/IComptroller.sol - + -35 +40 <<Interface>> IVault ../contracts/interfaces/IVault.sol - + + +180 + +VaultStorage +../contracts/vault/VaultStorage.sol + + + +40->180 + + + + -110 +125 <<Abstract>> BaseCompoundStrategy ../contracts/strategies/BaseCompoundStrategy.sol - + -126 +142 <<Interface>> ICERC20 ../contracts/strategies/ICompound.sol - - -110->126 + + +125->142 - - -150 + + +168 <<Abstract>> InitializableAbstractStrategy ../contracts/utils/InitializableAbstractStrategy.sol - - -110->150 + + +125->168 - + -114 +129 CompoundStrategy ../contracts/strategies/CompoundStrategy.sol - - -114->22 + + +129->22 - - -114->110 + + +129->125 - - -114->126 + + +129->142 - + -149 - -<<Abstract>> -Initializable -../contracts/utils/Initializable.sol +159 + +OUSD +../contracts/token/OUSD.sol - - -150->7 - - + + +159->7 + + - - -150->35 + + +167 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol + + + +159->167 + + + + + +170 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol + + + +159->170 + + + + + +168->7 + + + + + +168->40 - - -150->149 - - + + +168->167 + + - - -150->150 + + +168->168 - - -436 - -<<Interface>> -IERC20 -../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - - - -150->436 - - + + +357 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + + +168->357 + + + + + +170->357 + + + + + +180->7 + + + + + +180->159 + + + + + +180->167 + + diff --git a/contracts/docs/CompStrategySquashed.svg b/contracts/docs/CompStrategySquashed.svg index 2a30c81e05..83a54ad35d 100644 --- a/contracts/docs/CompStrategySquashed.svg +++ b/contracts/docs/CompStrategySquashed.svg @@ -4,92 +4,95 @@ - - + + UmlClassDiagram - - + + -114 - -CompoundStrategy -../contracts/strategies/CompoundStrategy.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _reserved: int256[98] <<InitializableAbstractStrategy>> -   __reserved: int256[50] <<BaseCompoundStrategy>> -Internal: -   assetsMapped: address[] <<InitializableAbstractStrategy>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   platformAddress: address <<InitializableAbstractStrategy>> -   vaultAddress: address <<InitializableAbstractStrategy>> -   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> -   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> -   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> -   harvesterAddress: address <<InitializableAbstractStrategy>> -   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>> - -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> -    _collectRewardTokens() <<InitializableAbstractStrategy>> -    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    _abstractSetPToken(_asset: address, _pToken: address) <<CompoundStrategy>> -    _getCTokenFor(_asset: address): ICERC20 <<BaseCompoundStrategy>> -    _convertUnderlyingToCToken(_cToken: ICERC20, _underlying: uint256): (amount: uint256) <<BaseCompoundStrategy>> -    _deposit(_asset: address, _amount: uint256) <<CompoundStrategy>> -    _checkBalance(_cToken: ICERC20): (balance: uint256) <<CompoundStrategy>> -External: -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> -    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<CompoundStrategy>> -    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> -    setPTokenAddress(_asset: address, _pToken: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    safeApproveAllTokens() <<CompoundStrategy>> -    deposit(_asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<CompoundStrategy>> -    depositAll() <<onlyVault, nonReentrant>> <<CompoundStrategy>> -    withdraw(_recipient: address, _asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<CompoundStrategy>> -    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<CompoundStrategy>> -    checkBalance(_asset: address): (balance: uint256) <<CompoundStrategy>> -    supportsAsset(_asset: address): bool <<BaseCompoundStrategy>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> -    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> -    <<event>> SkippedWithdrawal(asset: address, amount: uint256) <<CompoundStrategy>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> -    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> -    constructor() <<Governable>> -    governor(): address <<Governable>> -    isGovernor(): bool <<Governable>> +129 + +CompoundStrategy +../contracts/strategies/CompoundStrategy.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_platformAddress: address <<InitializableAbstractStrategy>> +   _deprecated_vaultAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +   _reserved: int256[98] <<InitializableAbstractStrategy>> +   __reserved: int256[50] <<BaseCompoundStrategy>> +Internal: +   assetsMapped: address[] <<InitializableAbstractStrategy>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   platformAddress: address <<InitializableAbstractStrategy>> +   vaultAddress: address <<InitializableAbstractStrategy>> +   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> +   harvesterAddress: address <<InitializableAbstractStrategy>> +   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> +    _collectRewardTokens() <<InitializableAbstractStrategy>> +    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    _abstractSetPToken(_asset: address, _pToken: address) <<CompoundStrategy>> +    _getCTokenFor(_asset: address): ICERC20 <<BaseCompoundStrategy>> +    _convertUnderlyingToCToken(_cToken: ICERC20, _underlying: uint256): (amount: uint256) <<BaseCompoundStrategy>> +    _deposit(_asset: address, _amount: uint256) <<CompoundStrategy>> +    _checkBalance(_cToken: ICERC20): (balance: uint256) <<CompoundStrategy>> +External: +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> +    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<CompoundStrategy>> +    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> +    setPTokenAddress(_asset: address, _pToken: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    safeApproveAllTokens() <<CompoundStrategy>> +    deposit(_asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<CompoundStrategy>> +    depositAll() <<onlyVault, nonReentrant>> <<CompoundStrategy>> +    withdraw(_recipient: address, _asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<CompoundStrategy>> +    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<CompoundStrategy>> +    checkBalance(_asset: address): (balance: uint256) <<CompoundStrategy>> +    supportsAsset(_asset: address): bool <<BaseCompoundStrategy>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> +    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> +    <<event>> SkippedWithdrawal(asset: address, amount: uint256) <<CompoundStrategy>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> +    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_stratConfig: BaseStrategyConfig) <<CompoundStrategy>>    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> diff --git a/contracts/docs/CompStrategyStorage.svg b/contracts/docs/CompStrategyStorage.svg index 9c80d88fb4..c8cfbe3378 100644 --- a/contracts/docs/CompStrategyStorage.svg +++ b/contracts/docs/CompStrategyStorage.svg @@ -51,13 +51,13 @@ uint256[50]: Initializable.______gap (1600) -unallocated (12) - -address: InitializableAbstractStrategy.platformAddress (20) +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_platformAddress (20) -unallocated (12) - -address: InitializableAbstractStrategy.vaultAddress (20) +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_vaultAddress (20) mapping(address=>address): InitializableAbstractStrategy.assetToPToken (32) diff --git a/contracts/docs/ConvexEthMetaStrategyHierarchy.svg b/contracts/docs/ConvexEthMetaStrategyHierarchy.svg index 61eda47fd4..0a74529fe9 100644 --- a/contracts/docs/ConvexEthMetaStrategyHierarchy.svg +++ b/contracts/docs/ConvexEthMetaStrategyHierarchy.svg @@ -4,154 +4,224 @@ - - + + UmlClassDiagram - + 7 - -Governable -../contracts/governance/Governable.sol + +Governable +../contracts/governance/Governable.sol - + -35 - -<<Interface>> -IVault -../contracts/interfaces/IVault.sol +40 + +<<Interface>> +IVault +../contracts/interfaces/IVault.sol + + + +180 + +VaultStorage +../contracts/vault/VaultStorage.sol + + + +40->180 + + - + -36 - -<<Interface>> -IWETH9 -../contracts/interfaces/IWETH9.sol +41 + +<<Interface>> +IWETH9 +../contracts/interfaces/IWETH9.sol - + -115 - -ConvexEthMetaStrategy -../contracts/strategies/ConvexEthMetaStrategy.sol +130 + +ConvexEthMetaStrategy +../contracts/strategies/ConvexEthMetaStrategy.sol - - -115->35 - - + + +130->40 + + - - -115->36 - - + + +130->41 + + - + -127 - -<<Interface>> -IConvexDeposits -../contracts/strategies/IConvexDeposits.sol +143 + +<<Interface>> +IConvexDeposits +../contracts/strategies/IConvexDeposits.sol - - -115->127 - - + + +130->143 + + - + -129 - -<<Interface>> -ICurveETHPoolV1 -../contracts/strategies/ICurveETHPoolV1.sol +144 + +<<Interface>> +ICurveETHPoolV1 +../contracts/strategies/ICurveETHPoolV1.sol - - -115->129 - - + + +130->144 + + - + -133 - -<<Interface>> -IRewardStaking -../contracts/strategies/IRewardStaking.sol +148 + +<<Interface>> +IRewardStaking +../contracts/strategies/IRewardStaking.sol - - -115->133 - - + + +130->148 + + - - -150 - -<<Abstract>> -InitializableAbstractStrategy -../contracts/utils/InitializableAbstractStrategy.sol + + +168 + +<<Abstract>> +InitializableAbstractStrategy +../contracts/utils/InitializableAbstractStrategy.sol - - -115->150 - - + + +130->168 + + - + -149 - -<<Abstract>> -Initializable -../contracts/utils/Initializable.sol - - - -150->7 - - +159 + +OUSD +../contracts/token/OUSD.sol - - -150->35 - - + + +159->7 + + - - -150->149 - - + + +167 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol - + + +159->167 + + + + + +170 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol + + -150->150 - - - - - -436 - -<<Interface>> -IERC20 -../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - - - -150->436 - - +159->170 + + + + + +168->7 + + + + + +168->40 + + + + + +168->167 + + + + + +168->168 + + + + + +357 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + + +168->357 + + + + + +170->357 + + + + + +180->7 + + + + + +180->159 + + + + + +180->167 + + diff --git a/contracts/docs/ConvexEthMetaStrategySquashed.svg b/contracts/docs/ConvexEthMetaStrategySquashed.svg index 379ac1ac15..3a964662b3 100644 --- a/contracts/docs/ConvexEthMetaStrategySquashed.svg +++ b/contracts/docs/ConvexEthMetaStrategySquashed.svg @@ -4,105 +4,108 @@ - - + + UmlClassDiagram - - + + -115 - -ConvexEthMetaStrategy -../contracts/strategies/ConvexEthMetaStrategy.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _reserved: int256[98] <<InitializableAbstractStrategy>> -Internal: -   assetsMapped: address[] <<InitializableAbstractStrategy>> -   MAX_SLIPPAGE: uint256 <<ConvexEthMetaStrategy>> -   ETH_ADDRESS: address <<ConvexEthMetaStrategy>> -   cvxDepositorAddress: address <<ConvexEthMetaStrategy>> -   cvxDepositorPTokenId: uint256 <<ConvexEthMetaStrategy>> -   curvePool: ICurveETHPoolV1 <<ConvexEthMetaStrategy>> -   lpToken: IERC20 <<ConvexEthMetaStrategy>> -   oeth: IERC20 <<ConvexEthMetaStrategy>> -   weth: IWETH9 <<ConvexEthMetaStrategy>> -   oethCoinIndex: uint128 <<ConvexEthMetaStrategy>> -   ethCoinIndex: uint128 <<ConvexEthMetaStrategy>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   platformAddress: address <<InitializableAbstractStrategy>> -   vaultAddress: address <<InitializableAbstractStrategy>> -   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> -   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> -   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> -   harvesterAddress: address <<InitializableAbstractStrategy>> -   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>> -   cvxRewardStaker: IRewardStaking <<ConvexEthMetaStrategy>> - -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> -    _collectRewardTokens() <<InitializableAbstractStrategy>> -    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    _abstractSetPToken(_asset: address, _pToken: address) <<ConvexEthMetaStrategy>> -    _deposit(_weth: address, _wethAmount: uint256) <<ConvexEthMetaStrategy>> -    calcTokenToBurn(_wethAmount: uint256): (lpToBurn: uint256) <<ConvexEthMetaStrategy>> -    _lpWithdraw(_wethAmount: uint256) <<ConvexEthMetaStrategy>> -    _approveAsset(_asset: address) <<ConvexEthMetaStrategy>> -    _approveBase() <<ConvexEthMetaStrategy>> -    _getCoinIndex(_asset: address): uint256 <<ConvexEthMetaStrategy>> -    _max(a: int256, b: int256): int256 <<ConvexEthMetaStrategy>> -External: -    <<payable>> null() <<ConvexEthMetaStrategy>> -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> -    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<ConvexEthMetaStrategy>> -    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> -    setPTokenAddress(_asset: address, _pToken: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> -    safeApproveAllTokens() <<onlyGovernor, nonReentrant>> <<ConvexEthMetaStrategy>> -    deposit(_weth: address, _amount: uint256) <<onlyVault, nonReentrant>> <<ConvexEthMetaStrategy>> -    depositAll() <<onlyVault, nonReentrant>> <<ConvexEthMetaStrategy>> -    withdraw(_recipient: address, _weth: address, _amount: uint256) <<onlyVault, nonReentrant>> <<ConvexEthMetaStrategy>> -    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<ConvexEthMetaStrategy>> -    supportsAsset(_asset: address): bool <<ConvexEthMetaStrategy>> -    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[], initConfig: InitialiseConfig) <<onlyGovernor, initializer>> <<ConvexEthMetaStrategy>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> -    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> -    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> -    constructor() <<Governable>> -    governor(): address <<Governable>> -    isGovernor(): bool <<Governable>> +130 + +ConvexEthMetaStrategy +../contracts/strategies/ConvexEthMetaStrategy.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_platformAddress: address <<InitializableAbstractStrategy>> +   _deprecated_vaultAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +   _reserved: int256[98] <<InitializableAbstractStrategy>> +Internal: +   assetsMapped: address[] <<InitializableAbstractStrategy>> +   MAX_SLIPPAGE: uint256 <<ConvexEthMetaStrategy>> +   ETH_ADDRESS: address <<ConvexEthMetaStrategy>> +   cvxDepositorAddress: address <<ConvexEthMetaStrategy>> +   cvxDepositorPTokenId: uint256 <<ConvexEthMetaStrategy>> +   curvePool: ICurveETHPoolV1 <<ConvexEthMetaStrategy>> +   lpToken: IERC20 <<ConvexEthMetaStrategy>> +   oeth: IERC20 <<ConvexEthMetaStrategy>> +   weth: IWETH9 <<ConvexEthMetaStrategy>> +   oethCoinIndex: uint128 <<ConvexEthMetaStrategy>> +   ethCoinIndex: uint128 <<ConvexEthMetaStrategy>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   platformAddress: address <<InitializableAbstractStrategy>> +   vaultAddress: address <<InitializableAbstractStrategy>> +   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> +   harvesterAddress: address <<InitializableAbstractStrategy>> +   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>> +   cvxRewardStaker: IRewardStaking <<ConvexEthMetaStrategy>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> +    _collectRewardTokens() <<InitializableAbstractStrategy>> +    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    _abstractSetPToken(_asset: address, _pToken: address) <<ConvexEthMetaStrategy>> +    _deposit(_weth: address, _wethAmount: uint256) <<ConvexEthMetaStrategy>> +    calcTokenToBurn(_wethAmount: uint256): (lpToBurn: uint256) <<ConvexEthMetaStrategy>> +    _lpWithdraw(_wethAmount: uint256) <<ConvexEthMetaStrategy>> +    _approveAsset(_asset: address) <<ConvexEthMetaStrategy>> +    _approveBase() <<ConvexEthMetaStrategy>> +    _getCoinIndex(_asset: address): uint256 <<ConvexEthMetaStrategy>> +    _max(a: int256, b: int256): int256 <<ConvexEthMetaStrategy>> +External: +    <<payable>> null() <<ConvexEthMetaStrategy>> +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> +    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<ConvexEthMetaStrategy>> +    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> +    setPTokenAddress(_asset: address, _pToken: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>> +    safeApproveAllTokens() <<onlyGovernor, nonReentrant>> <<ConvexEthMetaStrategy>> +    deposit(_weth: address, _amount: uint256) <<onlyVault, nonReentrant>> <<ConvexEthMetaStrategy>> +    depositAll() <<onlyVault, nonReentrant>> <<ConvexEthMetaStrategy>> +    withdraw(_recipient: address, _weth: address, _amount: uint256) <<onlyVault, nonReentrant>> <<ConvexEthMetaStrategy>> +    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<ConvexEthMetaStrategy>> +    supportsAsset(_asset: address): bool <<ConvexEthMetaStrategy>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[], initConfig: InitializeConfig) <<onlyGovernor, initializer>> <<ConvexEthMetaStrategy>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> +    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> +    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_stratConfig: BaseStrategyConfig) <<ConvexEthMetaStrategy>>    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>>    checkBalance(_asset: address): (balance: uint256) <<ConvexEthMetaStrategy>> diff --git a/contracts/docs/FraxETHStrategyHierarchy.svg b/contracts/docs/FraxETHStrategyHierarchy.svg index 096d417846..8db2a381c3 100644 --- a/contracts/docs/FraxETHStrategyHierarchy.svg +++ b/contracts/docs/FraxETHStrategyHierarchy.svg @@ -24,227 +24,227 @@ IFraxETHMinter ../contracts/interfaces/IFraxETHMinter.sol - + -36 +40 <<Interface>> IVault ../contracts/interfaces/IVault.sol - + -169 +180 VaultStorage ../contracts/vault/VaultStorage.sol - + -36->169 +40->180 - + -37 +41 <<Interface>> IWETH9 ../contracts/interfaces/IWETH9.sol - + -127 +135 FraxETHStrategy ../contracts/strategies/FraxETHStrategy.sol - + -127->25 +135->25 - + -127->37 +135->41 - + -128 +136 Generalized4626Strategy ../contracts/strategies/Generalized4626Strategy.sol - + -127->128 +135->136 - + -206 +233 <<Interface>> IERC4626 ../lib/openzeppelin/interfaces/IERC4626.sol - + -127->206 +135->233 - + -158 +168 <<Abstract>> InitializableAbstractStrategy ../contracts/utils/InitializableAbstractStrategy.sol - + -128->158 +136->168 - + -128->206 +136->233 - + -150 +159 OUSD ../contracts/token/OUSD.sol - + -150->7 +159->7 - + -157 +167 <<Abstract>> Initializable ../contracts/utils/Initializable.sol - + -150->157 +159->167 - + -159 +170 <<Abstract>> InitializableERC20Detailed ../contracts/utils/InitializableERC20Detailed.sol - + -150->159 +159->170 - + -158->7 +168->7 - + -158->36 +168->40 - + -158->157 +168->167 - + -158->158 +168->168 - + -359 +357 <<Interface>> IERC20 ../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - + -158->359 +168->357 - + -159->359 +170->357 - + -169->7 +180->7 - + -169->150 +180->159 - + -169->157 +180->167 - + -206->359 +233->357 - + -731 +728 <<Interface>> IERC20Metadata ../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol - + -206->731 +233->728 - + -731->359 +728->357 diff --git a/contracts/docs/FraxETHStrategySquashed.svg b/contracts/docs/FraxETHStrategySquashed.svg index 3225cf2e64..45637c3fc7 100644 --- a/contracts/docs/FraxETHStrategySquashed.svg +++ b/contracts/docs/FraxETHStrategySquashed.svg @@ -4,51 +4,53 @@ - - + + UmlClassDiagram - - + + -127 - -FraxETHStrategy -../contracts/strategies/FraxETHStrategy.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _reserved: int256[98] <<InitializableAbstractStrategy>> -   __gap: uint256[50] <<Generalized4626Strategy>> -Internal: -   assetsMapped: address[] <<InitializableAbstractStrategy>> -   shareToken: IERC20 <<Generalized4626Strategy>> -   assetToken: IERC20 <<Generalized4626Strategy>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   platformAddress: address <<InitializableAbstractStrategy>> -   vaultAddress: address <<InitializableAbstractStrategy>> -   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> -   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> -   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +135 + +FraxETHStrategy +../contracts/strategies/FraxETHStrategy.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_platformAddress: address <<InitializableAbstractStrategy>> +   _deprecated_vaultAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +   _reserved: int256[98] <<InitializableAbstractStrategy>> +   __gap: uint256[50] <<Generalized4626Strategy>> +Internal: +   assetsMapped: address[] <<InitializableAbstractStrategy>> +   shareToken: IERC20 <<Generalized4626Strategy>> +   assetToken: IERC20 <<Generalized4626Strategy>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   platformAddress: address <<InitializableAbstractStrategy>> +   vaultAddress: address <<InitializableAbstractStrategy>> +   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>>   harvesterAddress: address <<InitializableAbstractStrategy>>   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>>   weth: address <<FraxETHStrategy>>   fraxETHMinter: IFraxETHMinter <<FraxETHStrategy>> - + Internal:    _governor(): (governorOut: address) <<Governable>>    _pendingGovernor(): (pendingGovernor: address) <<Governable>>    _setGovernor(newGovernor: address) <<Governable>>    _setPendingGovernor(newGovernor: address) <<Governable>>    _changeGovernor(_newGovernor: address) <<Governable>> -    _initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> +    _initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>>    _collectRewardTokens() <<InitializableAbstractStrategy>>    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>>    _abstractSetPToken(_asset: address, _pToken: address) <<Generalized4626Strategy>> @@ -57,7 +59,7 @@    <<payable>> null() <<FraxETHStrategy>>    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>>    claimGovernance() <<Governable>> -    initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>>    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<InitializableAbstractStrategy>>    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>>    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> @@ -84,14 +86,14 @@    <<modifier>> initializer() <<Initializable>>    <<modifier>> onlyGovernor() <<Governable>>    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> nonReentrantView() <<Governable>> -    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> -    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> -    constructor() <<Governable>> -    governor(): address <<Governable>> -    isGovernor(): bool <<Governable>> +    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> +    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_stratConfig: BaseStrategyConfig) <<FraxETHStrategy>>    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> diff --git a/contracts/docs/MorphoAaveStrategyHierarchy.svg b/contracts/docs/MorphoAaveStrategyHierarchy.svg index 69e3e55c41..4e8e81c4d8 100644 --- a/contracts/docs/MorphoAaveStrategyHierarchy.svg +++ b/contracts/docs/MorphoAaveStrategyHierarchy.svg @@ -4,160 +4,230 @@ - - + + UmlClassDiagram - + 7 - -Governable -../contracts/governance/Governable.sol + +Governable +../contracts/governance/Governable.sol 22 - + <<Interface>> IComptroller ../contracts/interfaces/IComptroller.sol - + -35 - -<<Interface>> -IVault -../contracts/interfaces/IVault.sol +42 + +<<Interface>> +IVault +../contracts/interfaces/IVault.sol + + + +182 + +VaultStorage +../contracts/vault/VaultStorage.sol + + + +42->182 + + - + -168 - -<<Interface>> -ILens -../contracts/interfaces/morpho/ILens.sol +199 + +<<Interface>> +ILens +../contracts/interfaces/morpho/ILens.sol - - -168->22 - - + + +199->22 + + - + -169 +200 <<Interface>> IMorpho ../contracts/interfaces/morpho/IMorpho.sol - - -168->169 - - + + +199->200 + + - + -296 - +235 + <<Interface>> ICompoundOracle ../contracts/interfaces/morpho/compound/ICompoundOracle.sol - - -168->296 - - - - + -169->22 - - +199->235 + + - + + +200->22 + + + + -134 - -MorphoAaveStrategy -../contracts/strategies/MorphoAaveStrategy.sol +151 + +MorphoAaveStrategy +../contracts/strategies/MorphoAaveStrategy.sol - - -134->168 - - + + +151->199 + + - - -134->169 - - + + +151->200 + + - - -150 - -<<Abstract>> -InitializableAbstractStrategy -../contracts/utils/InitializableAbstractStrategy.sol + + +170 + +<<Abstract>> +InitializableAbstractStrategy +../contracts/utils/InitializableAbstractStrategy.sol - - -134->150 - - + + +151->170 + + - + -149 - -<<Abstract>> -Initializable -../contracts/utils/Initializable.sol - - - -150->7 - - +161 + +OUSD +../contracts/token/OUSD.sol - - -150->35 - - + + +161->7 + + - - -150->149 - - + + +169 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol - + + +161->169 + + + + + +172 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol + + -150->150 - - - - - -436 - -<<Interface>> -IERC20 -../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - - - -150->436 - - +161->172 + + + + + +170->7 + + + + + +170->42 + + + + + +170->169 + + + + + +170->170 + + + + + +358 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + + +170->358 + + + + + +172->358 + + + + + +182->7 + + + + + +182->161 + + + + + +182->169 + + diff --git a/contracts/docs/MorphoAaveStrategySquashed.svg b/contracts/docs/MorphoAaveStrategySquashed.svg index e87915427c..53862302c3 100644 --- a/contracts/docs/MorphoAaveStrategySquashed.svg +++ b/contracts/docs/MorphoAaveStrategySquashed.svg @@ -4,48 +4,50 @@ - - + + UmlClassDiagram - - + + -134 - -MorphoAaveStrategy -../contracts/strategies/MorphoAaveStrategy.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _reserved: int256[98] <<InitializableAbstractStrategy>> -Internal: -   assetsMapped: address[] <<InitializableAbstractStrategy>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   platformAddress: address <<InitializableAbstractStrategy>> -   vaultAddress: address <<InitializableAbstractStrategy>> -   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> -   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> -   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +151 + +MorphoAaveStrategy +../contracts/strategies/MorphoAaveStrategy.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_platformAddress: address <<InitializableAbstractStrategy>> +   _deprecated_vaultAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +   _reserved: int256[98] <<InitializableAbstractStrategy>> +Internal: +   assetsMapped: address[] <<InitializableAbstractStrategy>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   platformAddress: address <<InitializableAbstractStrategy>> +   vaultAddress: address <<InitializableAbstractStrategy>> +   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>>   harvesterAddress: address <<InitializableAbstractStrategy>>   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>>   MORPHO: address <<MorphoAaveStrategy>>   LENS: address <<MorphoAaveStrategy>> - + Internal:    _governor(): (governorOut: address) <<Governable>>    _pendingGovernor(): (pendingGovernor: address) <<Governable>>    _setGovernor(newGovernor: address) <<Governable>>    _setPendingGovernor(newGovernor: address) <<Governable>>    _changeGovernor(_newGovernor: address) <<Governable>> -    _initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> +    _initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>>    _collectRewardTokens() <<InitializableAbstractStrategy>>    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>>    _abstractSetPToken(_asset: address, _pToken: address) <<MorphoAaveStrategy>> @@ -56,7 +58,7 @@ External:    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>>    claimGovernance() <<Governable>> -    initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<MorphoAaveStrategy>>    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<MorphoAaveStrategy>>    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>>    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> @@ -70,28 +72,28 @@    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<MorphoAaveStrategy>>    checkBalance(_asset: address): (balance: uint256) <<MorphoAaveStrategy>>    supportsAsset(_asset: address): bool <<MorphoAaveStrategy>> -    initialize(_vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<MorphoAaveStrategy>> -    getPendingRewards(): (balance: uint256) <<MorphoAaveStrategy>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> -    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> -    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> -    constructor() <<Governable>> -    governor(): address <<Governable>> -    isGovernor(): bool <<Governable>> +    getPendingRewards(): (balance: uint256) <<MorphoAaveStrategy>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> +    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> +    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_stratConfig: BaseStrategyConfig) <<MorphoAaveStrategy>>    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> diff --git a/contracts/docs/MorphoAaveStrategyStorage.svg b/contracts/docs/MorphoAaveStrategyStorage.svg index f733fc4730..3ac3ef41cf 100644 --- a/contracts/docs/MorphoAaveStrategyStorage.svg +++ b/contracts/docs/MorphoAaveStrategyStorage.svg @@ -49,13 +49,13 @@ uint256[50]: Initializable.______gap (1600) -unallocated (12) - -address: InitializableAbstractStrategy.platformAddress (20) +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_platformAddress (20) -unallocated (12) - -address: InitializableAbstractStrategy.vaultAddress (20) +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_vaultAddress (20) mapping(address=>address): InitializableAbstractStrategy.assetToPToken (32) diff --git a/contracts/docs/MorphoCompStrategyHierarchy.svg b/contracts/docs/MorphoCompStrategyHierarchy.svg index 87e4039d5a..1c2f5de7f7 100644 --- a/contracts/docs/MorphoCompStrategyHierarchy.svg +++ b/contracts/docs/MorphoCompStrategyHierarchy.svg @@ -4,17 +4,17 @@ - - + + UmlClassDiagram - + 7 - -Governable -../contracts/governance/Governable.sol + +Governable +../contracts/governance/Governable.sol @@ -24,168 +24,238 @@ IComptroller ../contracts/interfaces/IComptroller.sol - + -35 +42 <<Interface>> IVault ../contracts/interfaces/IVault.sol - + + +182 + +VaultStorage +../contracts/vault/VaultStorage.sol + + + +42->182 + + + + -168 +199 <<Interface>> ILens ../contracts/interfaces/morpho/ILens.sol - - -168->22 + + +199->22 - + -169 +200 <<Interface>> IMorpho ../contracts/interfaces/morpho/IMorpho.sol - - -168->169 + + +199->200 - + -296 +235 <<Interface>> ICompoundOracle ../contracts/interfaces/morpho/compound/ICompoundOracle.sol - - -168->296 + + +199->235 - - -169->22 + + +200->22 - + -110 +127 <<Abstract>> BaseCompoundStrategy ../contracts/strategies/BaseCompoundStrategy.sol - + -126 +144 <<Interface>> ICERC20 ../contracts/strategies/ICompound.sol - - -110->126 + + +127->144 - - -150 + + +170 <<Abstract>> InitializableAbstractStrategy ../contracts/utils/InitializableAbstractStrategy.sol - - -110->150 + + +127->170 - + -135 +152 MorphoCompoundStrategy ../contracts/strategies/MorphoCompoundStrategy.sol - - -135->168 + + +152->199 - - -135->169 + + +152->200 - - -135->110 + + +152->127 - + -149 - -<<Abstract>> -Initializable -../contracts/utils/Initializable.sol +161 + +OUSD +../contracts/token/OUSD.sol + + + +161->7 + + - + + +169 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol + + -150->7 - - +161->169 + + - - -150->35 + + +172 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol + + + +161->172 + + + + + +170->7 + + + + + +170->42 - - -150->149 - - + + +170->169 + + - - -150->150 + + +170->170 - - -436 - -<<Interface>> -IERC20 -../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + +358 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - - -150->436 - - + + +170->358 + + + + + +172->358 + + + + + +182->7 + + + + + +182->161 + + + + + +182->169 + + diff --git a/contracts/docs/MorphoCompStrategySquashed.svg b/contracts/docs/MorphoCompStrategySquashed.svg index eb9d5fba89..47bd0be925 100644 --- a/contracts/docs/MorphoCompStrategySquashed.svg +++ b/contracts/docs/MorphoCompStrategySquashed.svg @@ -4,49 +4,51 @@ - - + + UmlClassDiagram - - + + -135 - -MorphoCompoundStrategy -../contracts/strategies/MorphoCompoundStrategy.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _reserved: int256[98] <<InitializableAbstractStrategy>> -   __reserved: int256[50] <<BaseCompoundStrategy>> -Internal: -   assetsMapped: address[] <<InitializableAbstractStrategy>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   platformAddress: address <<InitializableAbstractStrategy>> -   vaultAddress: address <<InitializableAbstractStrategy>> -   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>> -   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> -   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +152 + +MorphoCompoundStrategy +../contracts/strategies/MorphoCompoundStrategy.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_platformAddress: address <<InitializableAbstractStrategy>> +   _deprecated_vaultAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>> +   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>> +   _reserved: int256[98] <<InitializableAbstractStrategy>> +   __reserved: int256[50] <<BaseCompoundStrategy>> +Internal: +   assetsMapped: address[] <<InitializableAbstractStrategy>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   platformAddress: address <<InitializableAbstractStrategy>> +   vaultAddress: address <<InitializableAbstractStrategy>> +   assetToPToken: mapping(address=>address) <<InitializableAbstractStrategy>>   harvesterAddress: address <<InitializableAbstractStrategy>>   rewardTokenAddresses: address[] <<InitializableAbstractStrategy>>   MORPHO: address <<MorphoCompoundStrategy>>   LENS: address <<MorphoCompoundStrategy>> - + Internal:    _governor(): (governorOut: address) <<Governable>>    _pendingGovernor(): (pendingGovernor: address) <<Governable>>    _setGovernor(newGovernor: address) <<Governable>>    _setPendingGovernor(newGovernor: address) <<Governable>>    _changeGovernor(_newGovernor: address) <<Governable>> -    _initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>> +    _initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<InitializableAbstractStrategy>>    _collectRewardTokens() <<InitializableAbstractStrategy>>    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>>    _abstractSetPToken(_asset: address, _pToken: address) <<MorphoCompoundStrategy>> @@ -58,7 +60,7 @@ External:    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>>    claimGovernance() <<Governable>> -    initialize(_platformAddress: address, _vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<InitializableAbstractStrategy>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<MorphoCompoundStrategy>>    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<MorphoCompoundStrategy>>    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>>    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> @@ -72,28 +74,28 @@    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<MorphoCompoundStrategy>>    checkBalance(_asset: address): (balance: uint256) <<MorphoCompoundStrategy>>    supportsAsset(_asset: address): bool <<BaseCompoundStrategy>> -    initialize(_vaultAddress: address, _rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<MorphoCompoundStrategy>> -    getPendingRewards(): (balance: uint256) <<MorphoCompoundStrategy>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> -    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> -    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> -    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> -    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> -    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> -    constructor() <<Governable>> -    governor(): address <<Governable>> -    isGovernor(): bool <<Governable>> +    getPendingRewards(): (balance: uint256) <<MorphoCompoundStrategy>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> PTokenAdded(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> PTokenRemoved(_asset: address, _pToken: address) <<InitializableAbstractStrategy>> +    <<event>> Deposit(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> Withdrawal(_asset: address, _pToken: address, _amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>> +    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>> +    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    <<modifier>> onlyVault() <<InitializableAbstractStrategy>> +    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>> +    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_stratConfig: BaseStrategyConfig) <<MorphoCompoundStrategy>>    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>> diff --git a/contracts/docs/MorphoCompStrategyStorage.svg b/contracts/docs/MorphoCompStrategyStorage.svg index 7ad57fe083..47d580b6b8 100644 --- a/contracts/docs/MorphoCompStrategyStorage.svg +++ b/contracts/docs/MorphoCompStrategyStorage.svg @@ -51,13 +51,13 @@ uint256[50]: Initializable.______gap (1600) -unallocated (12) - -address: InitializableAbstractStrategy.platformAddress (20) +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_platformAddress (20) -unallocated (12) - -address: InitializableAbstractStrategy.vaultAddress (20) +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_vaultAddress (20) mapping(address=>address): InitializableAbstractStrategy.assetToPToken (32) diff --git a/contracts/docs/OETHVaultAdminSquashed.svg b/contracts/docs/OETHVaultAdminSquashed.svg index 5bd6087887..2a93a878e1 100644 --- a/contracts/docs/OETHVaultAdminSquashed.svg +++ b/contracts/docs/OETHVaultAdminSquashed.svg @@ -4,137 +4,135 @@ - - + + UmlClassDiagram - - + + -169 - -OETHVaultAdmin -../contracts/vault/OETHVaultAdmin.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _deprecated_rebaseHooksAddr: address <<VaultStorage>> -   _deprecated_uniswapAddr: address <<VaultStorage>> -   _deprecated_swapTokens: address[] <<VaultStorage>> -Internal: -   assets: mapping(address=>Asset) <<VaultStorage>> -   allAssets: address[] <<VaultStorage>> -   strategies: mapping(address=>Strategy) <<VaultStorage>> -   allStrategies: address[] <<VaultStorage>> -   oUSD: OUSD <<VaultStorage>> -   swapConfig: SwapConfig <<VaultStorage>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   priceProvider: address <<VaultStorage>> -   rebasePaused: bool <<VaultStorage>> -   capitalPaused: bool <<VaultStorage>> -   redeemFeeBps: uint256 <<VaultStorage>> -   vaultBuffer: uint256 <<VaultStorage>> -   autoAllocateThreshold: uint256 <<VaultStorage>> -   rebaseThreshold: uint256 <<VaultStorage>> -   adminImplPosition: bytes32 <<VaultStorage>> -   strategistAddr: address <<VaultStorage>> -   assetDefaultStrategies: mapping(address=>address) <<VaultStorage>> -   maxSupplyDiff: uint256 <<VaultStorage>> -   trusteeAddress: address <<VaultStorage>> -   trusteeFeeBps: uint256 <<VaultStorage>> -   MINT_MINIMUM_UNIT_PRICE: uint256 <<VaultStorage>> -   ousdMetaStrategy: address <<VaultStorage>> -   netOusdMintedForStrategy: int256 <<VaultStorage>> -   netOusdMintForStrategyThreshold: uint256 <<VaultStorage>> -   MIN_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> -   MAX_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> - -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _postSwapChecks(_fromAsset: address, _fromAssetAmount: uint256, fromAssetConfig: Asset, _toAsset: address, toAssetAmount: uint256, _minToAssetAmount: uint256, toAssetConfig: Asset, config: SwapConfig) <<VaultAdmin>> -    _depositToStrategy(_strategyToAddress: address, _assets: address[], _amounts: uint256[]) <<VaultAdmin>> -    _withdrawFromStrategy(_recipient: address, _strategyFromAddress: address, _assets: address[], _amounts: uint256[]) <<VaultAdmin>> -    _cacheDecimals(token: address) <<VaultAdmin>> -External: -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    setAdminImpl(newImpl: address) <<onlyGovernor>> <<VaultStorage>> -    setPriceProvider(_priceProvider: address) <<onlyGovernor>> <<VaultAdmin>> -    setRedeemFeeBps(_redeemFeeBps: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setVaultBuffer(_vaultBuffer: uint256) <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    setAutoAllocateThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setRebaseThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setStrategistAddr(_address: address) <<onlyGovernor>> <<VaultAdmin>> -    setAssetDefaultStrategy(_asset: address, _strategy: address) <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    setNetOusdMintForStrategyThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> -    swapCollateral(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _minToAssetAmount: uint256, _data: bytes): (toAssetAmount: uint256) <<nonReentrant, onlyGovernorOrStrategist>> <<VaultAdmin>> -    setSwapper(_swapperAddr: address) <<onlyGovernor>> <<VaultAdmin>> -    swapper(): (swapper_: address) <<VaultAdmin>> -    setSwapAllowedUndervalue(_basis: uint16) <<onlyGovernor>> <<VaultAdmin>> -    allowedSwapUndervalue(): (value: uint256) <<VaultAdmin>> -    setOracleSlippage(_asset: address, _allowedOracleSlippageBps: uint16) <<onlyGovernor>> <<VaultAdmin>> -    supportAsset(_asset: address, _unitConversion: uint8) <<onlyGovernor>> <<VaultAdmin>> -    cacheDecimals(_asset: address) <<onlyGovernor>> <<VaultAdmin>> -    approveStrategy(_addr: address) <<onlyGovernor>> <<VaultAdmin>> -    removeStrategy(_addr: address) <<onlyGovernor>> <<VaultAdmin>> -    depositToStrategy(_strategyToAddress: address, _assets: address[], _amounts: uint256[]) <<onlyGovernorOrStrategist, nonReentrant>> <<VaultAdmin>> -    withdrawFromStrategy(_strategyFromAddress: address, _assets: address[], _amounts: uint256[]) <<onlyGovernorOrStrategist, nonReentrant>> <<VaultAdmin>> -    setMaxSupplyDiff(_maxSupplyDiff: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setTrusteeAddress(_address: address) <<onlyGovernor>> <<VaultAdmin>> -    setTrusteeFeeBps(_basis: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setOusdMetaStrategy(_ousdMetaStrategy: address) <<onlyGovernor>> <<VaultAdmin>> -    pauseRebase() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    unpauseRebase() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    pauseCapital() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    unpauseCapital() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<VaultAdmin>> -    withdrawAllFromStrategy(_strategyAddr: address) <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    withdrawAllFromStrategies() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> AssetSupported(_asset: address) <<VaultStorage>> -    <<event>> AssetDefaultStrategyUpdated(_asset: address, _strategy: address) <<VaultStorage>> -    <<event>> AssetAllocated(_asset: address, _strategy: address, _amount: uint256) <<VaultStorage>> -    <<event>> StrategyApproved(_addr: address) <<VaultStorage>> -    <<event>> StrategyRemoved(_addr: address) <<VaultStorage>> -    <<event>> Mint(_addr: address, _value: uint256) <<VaultStorage>> -    <<event>> Redeem(_addr: address, _value: uint256) <<VaultStorage>> -    <<event>> CapitalPaused() <<VaultStorage>> -    <<event>> CapitalUnpaused() <<VaultStorage>> -    <<event>> RebasePaused() <<VaultStorage>> -    <<event>> RebaseUnpaused() <<VaultStorage>> -    <<event>> VaultBufferUpdated(_vaultBuffer: uint256) <<VaultStorage>> -    <<event>> OusdMetaStrategyUpdated(_ousdMetaStrategy: address) <<VaultStorage>> -    <<event>> RedeemFeeUpdated(_redeemFeeBps: uint256) <<VaultStorage>> -    <<event>> PriceProviderUpdated(_priceProvider: address) <<VaultStorage>> -    <<event>> AllocateThresholdUpdated(_threshold: uint256) <<VaultStorage>> -    <<event>> RebaseThresholdUpdated(_threshold: uint256) <<VaultStorage>> -    <<event>> StrategistUpdated(_address: address) <<VaultStorage>> -    <<event>> MaxSupplyDiffChanged(maxSupplyDiff: uint256) <<VaultStorage>> -    <<event>> YieldDistribution(_to: address, _yield: uint256, _fee: uint256) <<VaultStorage>> -    <<event>> TrusteeFeeBpsChanged(_basis: uint256) <<VaultStorage>> -    <<event>> TrusteeAddressChanged(_address: address) <<VaultStorage>> -    <<event>> NetOusdMintForStrategyThresholdChanged(_threshold: uint256) <<VaultStorage>> -    <<event>> SwapperChanged(_address: address) <<VaultStorage>> -    <<event>> SwapAllowedUndervalueChanged(_basis: uint256) <<VaultStorage>> -    <<event>> SwapSlippageChanged(_asset: address, _basis: uint256) <<VaultStorage>> -    <<event>> Swapped(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _toAssetAmount: uint256) <<VaultStorage>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> nonReentrantView() <<Governable>> +175 + +OETHVaultAdmin +../contracts/vault/OETHVaultAdmin.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_rebaseHooksAddr: address <<VaultStorage>> +   _deprecated_uniswapAddr: address <<VaultStorage>> +   _deprecated_swapTokens: address[] <<VaultStorage>> +Internal: +   assets: mapping(address=>Asset) <<VaultStorage>> +   allAssets: address[] <<VaultStorage>> +   strategies: mapping(address=>Strategy) <<VaultStorage>> +   allStrategies: address[] <<VaultStorage>> +   oUSD: OUSD <<VaultStorage>> +   swapConfig: SwapConfig <<VaultStorage>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   priceProvider: address <<VaultStorage>> +   rebasePaused: bool <<VaultStorage>> +   capitalPaused: bool <<VaultStorage>> +   redeemFeeBps: uint256 <<VaultStorage>> +   vaultBuffer: uint256 <<VaultStorage>> +   autoAllocateThreshold: uint256 <<VaultStorage>> +   rebaseThreshold: uint256 <<VaultStorage>> +   adminImplPosition: bytes32 <<VaultStorage>> +   strategistAddr: address <<VaultStorage>> +   assetDefaultStrategies: mapping(address=>address) <<VaultStorage>> +   maxSupplyDiff: uint256 <<VaultStorage>> +   trusteeAddress: address <<VaultStorage>> +   trusteeFeeBps: uint256 <<VaultStorage>> +   MINT_MINIMUM_UNIT_PRICE: uint256 <<VaultStorage>> +   ousdMetaStrategy: address <<VaultStorage>> +   netOusdMintedForStrategy: int256 <<VaultStorage>> +   netOusdMintForStrategyThreshold: uint256 <<VaultStorage>> +   MIN_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> +   MAX_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _depositToStrategy(_strategyToAddress: address, _assets: address[], _amounts: uint256[]) <<VaultAdmin>> +    _withdrawFromStrategy(_recipient: address, _strategyFromAddress: address, _assets: address[], _amounts: uint256[]) <<VaultAdmin>> +    _cacheDecimals(token: address) <<VaultAdmin>> +External: +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    setAdminImpl(newImpl: address) <<onlyGovernor>> <<VaultStorage>> +    setPriceProvider(_priceProvider: address) <<onlyGovernor>> <<VaultAdmin>> +    setRedeemFeeBps(_redeemFeeBps: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setVaultBuffer(_vaultBuffer: uint256) <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    setAutoAllocateThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setRebaseThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setStrategistAddr(_address: address) <<onlyGovernor>> <<VaultAdmin>> +    setAssetDefaultStrategy(_asset: address, _strategy: address) <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    setNetOusdMintForStrategyThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> +    swapCollateral(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _minToAssetAmount: uint256, _data: bytes): (toAssetAmount: uint256) <<nonReentrant, onlyGovernorOrStrategist>> <<VaultAdmin>> +    setSwapper(_swapperAddr: address) <<onlyGovernor>> <<VaultAdmin>> +    swapper(): (swapper_: address) <<VaultAdmin>> +    setSwapAllowedUndervalue(_basis: uint16) <<onlyGovernor>> <<VaultAdmin>> +    allowedSwapUndervalue(): (value: uint256) <<VaultAdmin>> +    setOracleSlippage(_asset: address, _allowedOracleSlippageBps: uint16) <<onlyGovernor>> <<VaultAdmin>> +    supportAsset(_asset: address, _unitConversion: uint8) <<onlyGovernor>> <<VaultAdmin>> +    cacheDecimals(_asset: address) <<onlyGovernor>> <<VaultAdmin>> +    approveStrategy(_addr: address) <<onlyGovernor>> <<VaultAdmin>> +    removeStrategy(_addr: address) <<onlyGovernor>> <<VaultAdmin>> +    depositToStrategy(_strategyToAddress: address, _assets: address[], _amounts: uint256[]) <<onlyGovernorOrStrategist, nonReentrant>> <<VaultAdmin>> +    withdrawFromStrategy(_strategyFromAddress: address, _assets: address[], _amounts: uint256[]) <<onlyGovernorOrStrategist, nonReentrant>> <<VaultAdmin>> +    setMaxSupplyDiff(_maxSupplyDiff: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setTrusteeAddress(_address: address) <<onlyGovernor>> <<VaultAdmin>> +    setTrusteeFeeBps(_basis: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setOusdMetaStrategy(_ousdMetaStrategy: address) <<onlyGovernor>> <<VaultAdmin>> +    pauseRebase() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    unpauseRebase() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    pauseCapital() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    unpauseCapital() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<VaultAdmin>> +    withdrawAllFromStrategy(_strategyAddr: address) <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    withdrawAllFromStrategies() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> AssetSupported(_asset: address) <<VaultStorage>> +    <<event>> AssetDefaultStrategyUpdated(_asset: address, _strategy: address) <<VaultStorage>> +    <<event>> AssetAllocated(_asset: address, _strategy: address, _amount: uint256) <<VaultStorage>> +    <<event>> StrategyApproved(_addr: address) <<VaultStorage>> +    <<event>> StrategyRemoved(_addr: address) <<VaultStorage>> +    <<event>> Mint(_addr: address, _value: uint256) <<VaultStorage>> +    <<event>> Redeem(_addr: address, _value: uint256) <<VaultStorage>> +    <<event>> CapitalPaused() <<VaultStorage>> +    <<event>> CapitalUnpaused() <<VaultStorage>> +    <<event>> RebasePaused() <<VaultStorage>> +    <<event>> RebaseUnpaused() <<VaultStorage>> +    <<event>> VaultBufferUpdated(_vaultBuffer: uint256) <<VaultStorage>> +    <<event>> OusdMetaStrategyUpdated(_ousdMetaStrategy: address) <<VaultStorage>> +    <<event>> RedeemFeeUpdated(_redeemFeeBps: uint256) <<VaultStorage>> +    <<event>> PriceProviderUpdated(_priceProvider: address) <<VaultStorage>> +    <<event>> AllocateThresholdUpdated(_threshold: uint256) <<VaultStorage>> +    <<event>> RebaseThresholdUpdated(_threshold: uint256) <<VaultStorage>> +    <<event>> StrategistUpdated(_address: address) <<VaultStorage>> +    <<event>> MaxSupplyDiffChanged(maxSupplyDiff: uint256) <<VaultStorage>> +    <<event>> YieldDistribution(_to: address, _yield: uint256, _fee: uint256) <<VaultStorage>> +    <<event>> TrusteeFeeBpsChanged(_basis: uint256) <<VaultStorage>> +    <<event>> TrusteeAddressChanged(_address: address) <<VaultStorage>> +    <<event>> NetOusdMintForStrategyThresholdChanged(_threshold: uint256) <<VaultStorage>> +    <<event>> SwapperChanged(_address: address) <<VaultStorage>> +    <<event>> SwapAllowedUndervalueChanged(_basis: uint256) <<VaultStorage>> +    <<event>> SwapSlippageChanged(_asset: address, _basis: uint256) <<VaultStorage>> +    <<event>> Swapped(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _toAssetAmount: uint256) <<VaultStorage>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>>    <<modifier>> onlyGovernorOrStrategist() <<VaultAdmin>>    constructor() <<Governable>>    governor(): address <<Governable>> diff --git a/contracts/docs/OETHVaultCoreSquashed.svg b/contracts/docs/OETHVaultCoreSquashed.svg index ecf18b26d2..4dfa1bc586 100644 --- a/contracts/docs/OETHVaultCoreSquashed.svg +++ b/contracts/docs/OETHVaultCoreSquashed.svg @@ -4,137 +4,136 @@ - - + + UmlClassDiagram - - + + -170 - -OETHVaultCore -../contracts/vault/OETHVaultCore.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _deprecated_rebaseHooksAddr: address <<VaultStorage>> -   _deprecated_uniswapAddr: address <<VaultStorage>> -   _deprecated_swapTokens: address[] <<VaultStorage>> -Internal: -   assets: mapping(address=>Asset) <<VaultStorage>> -   allAssets: address[] <<VaultStorage>> -   strategies: mapping(address=>Strategy) <<VaultStorage>> -   allStrategies: address[] <<VaultStorage>> -   oUSD: OUSD <<VaultStorage>> -   swapConfig: SwapConfig <<VaultStorage>> -   MAX_INT: uint256 <<VaultCore>> -   MAX_UINT: uint256 <<VaultCore>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   priceProvider: address <<VaultStorage>> -   rebasePaused: bool <<VaultStorage>> -   capitalPaused: bool <<VaultStorage>> -   redeemFeeBps: uint256 <<VaultStorage>> -   vaultBuffer: uint256 <<VaultStorage>> -   autoAllocateThreshold: uint256 <<VaultStorage>> -   rebaseThreshold: uint256 <<VaultStorage>> -   adminImplPosition: bytes32 <<VaultStorage>> -   strategistAddr: address <<VaultStorage>> -   assetDefaultStrategies: mapping(address=>address) <<VaultStorage>> -   maxSupplyDiff: uint256 <<VaultStorage>> -   trusteeAddress: address <<VaultStorage>> -   trusteeFeeBps: uint256 <<VaultStorage>> -   MINT_MINIMUM_UNIT_PRICE: uint256 <<VaultStorage>> -   ousdMetaStrategy: address <<VaultStorage>> -   netOusdMintedForStrategy: int256 <<VaultStorage>> -   netOusdMintForStrategyThreshold: uint256 <<VaultStorage>> -   MIN_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> -   MAX_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> - -Private: -    abs(x: int256): uint256 <<VaultCore>> -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _redeem(_amount: uint256, _minimumUnitAmount: uint256) <<VaultCore>> -    _allocate() <<VaultCore>> -    _rebase(): uint256 <<whenNotRebasePaused>> <<VaultCore>> -    _totalValue(): (value: uint256) <<VaultCore>> -    _totalValueInVault(): (value: uint256) <<VaultCore>> -    _totalValueInStrategies(): (value: uint256) <<VaultCore>> -    _totalValueInStrategy(_strategyAddr: address): (value: uint256) <<VaultCore>> -    _checkBalance(_asset: address): (balance: uint256) <<VaultCore>> -    _calculateRedeemOutputs(_amount: uint256): (outputs: uint256[]) <<VaultCore>> -    _toUnits(_raw: uint256, _asset: address): uint256 <<VaultCore>> -    _toUnitPrice(_asset: address, isMint: bool): (price: uint256) <<VaultCore>> -    _getDecimals(_asset: address): (decimals: uint256) <<VaultCore>> -External: -    <<payable>> null() <<VaultCore>> -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    setAdminImpl(newImpl: address) <<onlyGovernor>> <<VaultStorage>> -    mint(_asset: address, _amount: uint256, _minimumOusdAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> -    mintForStrategy(_amount: uint256) <<whenNotCapitalPaused, onlyOusdMetaStrategy>> <<VaultCore>> -    redeem(_amount: uint256, _minimumUnitAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> -    burnForStrategy(_amount: uint256) <<whenNotCapitalPaused, onlyOusdMetaStrategy>> <<VaultCore>> -    redeemAll(_minimumUnitAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> -    allocate() <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> -    rebase() <<nonReentrant>> <<VaultCore>> -    totalValue(): (value: uint256) <<VaultCore>> -    checkBalance(_asset: address): uint256 <<VaultCore>> -    calculateRedeemOutputs(_amount: uint256): uint256[] <<VaultCore>> -    priceUnitMint(asset: address): (price: uint256) <<VaultCore>> -    priceUnitRedeem(asset: address): (price: uint256) <<VaultCore>> -    getAllAssets(): address[] <<VaultCore>> -    getStrategyCount(): uint256 <<VaultCore>> -    getAllStrategies(): address[] <<VaultCore>> -    isSupportedAsset(_asset: address): bool <<VaultCore>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> AssetSupported(_asset: address) <<VaultStorage>> -    <<event>> AssetDefaultStrategyUpdated(_asset: address, _strategy: address) <<VaultStorage>> -    <<event>> AssetAllocated(_asset: address, _strategy: address, _amount: uint256) <<VaultStorage>> -    <<event>> StrategyApproved(_addr: address) <<VaultStorage>> -    <<event>> StrategyRemoved(_addr: address) <<VaultStorage>> -    <<event>> Mint(_addr: address, _value: uint256) <<VaultStorage>> -    <<event>> Redeem(_addr: address, _value: uint256) <<VaultStorage>> -    <<event>> CapitalPaused() <<VaultStorage>> -    <<event>> CapitalUnpaused() <<VaultStorage>> -    <<event>> RebasePaused() <<VaultStorage>> -    <<event>> RebaseUnpaused() <<VaultStorage>> -    <<event>> VaultBufferUpdated(_vaultBuffer: uint256) <<VaultStorage>> -    <<event>> OusdMetaStrategyUpdated(_ousdMetaStrategy: address) <<VaultStorage>> -    <<event>> RedeemFeeUpdated(_redeemFeeBps: uint256) <<VaultStorage>> -    <<event>> PriceProviderUpdated(_priceProvider: address) <<VaultStorage>> -    <<event>> AllocateThresholdUpdated(_threshold: uint256) <<VaultStorage>> -    <<event>> RebaseThresholdUpdated(_threshold: uint256) <<VaultStorage>> -    <<event>> StrategistUpdated(_address: address) <<VaultStorage>> -    <<event>> MaxSupplyDiffChanged(maxSupplyDiff: uint256) <<VaultStorage>> -    <<event>> YieldDistribution(_to: address, _yield: uint256, _fee: uint256) <<VaultStorage>> -    <<event>> TrusteeFeeBpsChanged(_basis: uint256) <<VaultStorage>> -    <<event>> TrusteeAddressChanged(_address: address) <<VaultStorage>> -    <<event>> NetOusdMintForStrategyThresholdChanged(_threshold: uint256) <<VaultStorage>> -    <<event>> SwapperChanged(_address: address) <<VaultStorage>> -    <<event>> SwapAllowedUndervalueChanged(_basis: uint256) <<VaultStorage>> -    <<event>> SwapSlippageChanged(_asset: address, _basis: uint256) <<VaultStorage>> -    <<event>> Swapped(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _toAssetAmount: uint256) <<VaultStorage>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> nonReentrantView() <<Governable>> -    <<modifier>> whenNotCapitalPaused() <<VaultCore>> -    <<modifier>> whenNotRebasePaused() <<VaultCore>> +176 + +OETHVaultCore +../contracts/vault/OETHVaultCore.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_rebaseHooksAddr: address <<VaultStorage>> +   _deprecated_uniswapAddr: address <<VaultStorage>> +   _deprecated_swapTokens: address[] <<VaultStorage>> +Internal: +   assets: mapping(address=>Asset) <<VaultStorage>> +   allAssets: address[] <<VaultStorage>> +   strategies: mapping(address=>Strategy) <<VaultStorage>> +   allStrategies: address[] <<VaultStorage>> +   oUSD: OUSD <<VaultStorage>> +   swapConfig: SwapConfig <<VaultStorage>> +   MAX_INT: uint256 <<VaultCore>> +   MAX_UINT: uint256 <<VaultCore>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   priceProvider: address <<VaultStorage>> +   rebasePaused: bool <<VaultStorage>> +   capitalPaused: bool <<VaultStorage>> +   redeemFeeBps: uint256 <<VaultStorage>> +   vaultBuffer: uint256 <<VaultStorage>> +   autoAllocateThreshold: uint256 <<VaultStorage>> +   rebaseThreshold: uint256 <<VaultStorage>> +   adminImplPosition: bytes32 <<VaultStorage>> +   strategistAddr: address <<VaultStorage>> +   assetDefaultStrategies: mapping(address=>address) <<VaultStorage>> +   maxSupplyDiff: uint256 <<VaultStorage>> +   trusteeAddress: address <<VaultStorage>> +   trusteeFeeBps: uint256 <<VaultStorage>> +   MINT_MINIMUM_UNIT_PRICE: uint256 <<VaultStorage>> +   ousdMetaStrategy: address <<VaultStorage>> +   netOusdMintedForStrategy: int256 <<VaultStorage>> +   netOusdMintForStrategyThreshold: uint256 <<VaultStorage>> +   MIN_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> +   MAX_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> + +Private: +    abs(x: int256): uint256 <<VaultCore>> +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _redeem(_amount: uint256, _minimumUnitAmount: uint256) <<VaultCore>> +    _allocate() <<VaultCore>> +    _rebase(): uint256 <<whenNotRebasePaused>> <<VaultCore>> +    _totalValue(): (value: uint256) <<VaultCore>> +    _totalValueInVault(): (value: uint256) <<VaultCore>> +    _totalValueInStrategies(): (value: uint256) <<VaultCore>> +    _totalValueInStrategy(_strategyAddr: address): (value: uint256) <<VaultCore>> +    _checkBalance(_asset: address): (balance: uint256) <<VaultCore>> +    _calculateRedeemOutputs(_amount: uint256): (outputs: uint256[]) <<VaultCore>> +    _toUnits(_raw: uint256, _asset: address): uint256 <<VaultCore>> +    _toUnitPrice(_asset: address, isMint: bool): (price: uint256) <<VaultCore>> +    _getDecimals(_asset: address): (decimals: uint256) <<VaultCore>> +External: +    <<payable>> null() <<VaultCore>> +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    setAdminImpl(newImpl: address) <<onlyGovernor>> <<VaultStorage>> +    mint(_asset: address, _amount: uint256, _minimumOusdAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> +    mintForStrategy(_amount: uint256) <<whenNotCapitalPaused, onlyOusdMetaStrategy>> <<VaultCore>> +    redeem(_amount: uint256, _minimumUnitAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> +    burnForStrategy(_amount: uint256) <<whenNotCapitalPaused, onlyOusdMetaStrategy>> <<VaultCore>> +    redeemAll(_minimumUnitAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> +    allocate() <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> +    rebase() <<nonReentrant>> <<VaultCore>> +    totalValue(): (value: uint256) <<VaultCore>> +    checkBalance(_asset: address): uint256 <<VaultCore>> +    calculateRedeemOutputs(_amount: uint256): uint256[] <<VaultCore>> +    priceUnitMint(asset: address): (price: uint256) <<VaultCore>> +    priceUnitRedeem(asset: address): (price: uint256) <<VaultCore>> +    getAllAssets(): address[] <<VaultCore>> +    getStrategyCount(): uint256 <<VaultCore>> +    getAllStrategies(): address[] <<VaultCore>> +    isSupportedAsset(_asset: address): bool <<VaultCore>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> AssetSupported(_asset: address) <<VaultStorage>> +    <<event>> AssetDefaultStrategyUpdated(_asset: address, _strategy: address) <<VaultStorage>> +    <<event>> AssetAllocated(_asset: address, _strategy: address, _amount: uint256) <<VaultStorage>> +    <<event>> StrategyApproved(_addr: address) <<VaultStorage>> +    <<event>> StrategyRemoved(_addr: address) <<VaultStorage>> +    <<event>> Mint(_addr: address, _value: uint256) <<VaultStorage>> +    <<event>> Redeem(_addr: address, _value: uint256) <<VaultStorage>> +    <<event>> CapitalPaused() <<VaultStorage>> +    <<event>> CapitalUnpaused() <<VaultStorage>> +    <<event>> RebasePaused() <<VaultStorage>> +    <<event>> RebaseUnpaused() <<VaultStorage>> +    <<event>> VaultBufferUpdated(_vaultBuffer: uint256) <<VaultStorage>> +    <<event>> OusdMetaStrategyUpdated(_ousdMetaStrategy: address) <<VaultStorage>> +    <<event>> RedeemFeeUpdated(_redeemFeeBps: uint256) <<VaultStorage>> +    <<event>> PriceProviderUpdated(_priceProvider: address) <<VaultStorage>> +    <<event>> AllocateThresholdUpdated(_threshold: uint256) <<VaultStorage>> +    <<event>> RebaseThresholdUpdated(_threshold: uint256) <<VaultStorage>> +    <<event>> StrategistUpdated(_address: address) <<VaultStorage>> +    <<event>> MaxSupplyDiffChanged(maxSupplyDiff: uint256) <<VaultStorage>> +    <<event>> YieldDistribution(_to: address, _yield: uint256, _fee: uint256) <<VaultStorage>> +    <<event>> TrusteeFeeBpsChanged(_basis: uint256) <<VaultStorage>> +    <<event>> TrusteeAddressChanged(_address: address) <<VaultStorage>> +    <<event>> NetOusdMintForStrategyThresholdChanged(_threshold: uint256) <<VaultStorage>> +    <<event>> SwapperChanged(_address: address) <<VaultStorage>> +    <<event>> SwapAllowedUndervalueChanged(_basis: uint256) <<VaultStorage>> +    <<event>> SwapSlippageChanged(_asset: address, _basis: uint256) <<VaultStorage>> +    <<event>> Swapped(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _toAssetAmount: uint256) <<VaultStorage>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    <<modifier>> whenNotRebasePaused() <<VaultCore>> +    <<modifier>> whenNotCapitalPaused() <<VaultCore>>    <<modifier>> onlyOusdMetaStrategy() <<VaultCore>>    constructor() <<Governable>>    governor(): address <<Governable>> diff --git a/contracts/docs/OETHVaultHierarchy.svg b/contracts/docs/OETHVaultHierarchy.svg index f70cf47d37..7ff52ea935 100644 --- a/contracts/docs/OETHVaultHierarchy.svg +++ b/contracts/docs/OETHVaultHierarchy.svg @@ -16,157 +16,157 @@ Governable ../contracts/governance/Governable.sol - + -26 +27 <<Interface>> IGetExchangeRateToken ../contracts/interfaces/IGetExchangeRateToken.sol - + -34 +35 <<Interface>> IOracle ../contracts/interfaces/IOracle.sol - + -37 +39 <<Interface>> IStrategy ../contracts/interfaces/IStrategy.sol - + -157 +161 OUSD ../contracts/token/OUSD.sol - + -157->7 +161->7 - + -164 +169 <<Abstract>> Initializable ../contracts/utils/Initializable.sol - + -157->164 +161->169 - + -166 +172 <<Abstract>> InitializableERC20Detailed ../contracts/utils/InitializableERC20Detailed.sol - + -157->166 +161->172 - + -338 +358 <<Interface>> IERC20 ../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - + -166->338 +172->358 - + -170 +176 OETHVaultCore ../contracts/vault/OETHVaultCore.sol - + -174 +180 VaultCore ../contracts/vault/VaultCore.sol - + -170->174 +176->180 - + -174->26 +180->27 - + -174->34 +180->35 - + -174->37 +180->39 - + -176 +182 VaultStorage ../contracts/vault/VaultStorage.sol - + -174->176 +180->182 - + -174->338 +180->358 - + -176->7 +182->7 - + -176->157 +182->161 - + -176->164 +182->169 diff --git a/contracts/docs/VaultAdminSquashed.svg b/contracts/docs/VaultAdminSquashed.svg index 4ec74fbfdc..ff0fc46a7b 100644 --- a/contracts/docs/VaultAdminSquashed.svg +++ b/contracts/docs/VaultAdminSquashed.svg @@ -4,137 +4,135 @@ - - + + UmlClassDiagram - - + + -173 - -VaultAdmin -../contracts/vault/VaultAdmin.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _deprecated_rebaseHooksAddr: address <<VaultStorage>> -   _deprecated_uniswapAddr: address <<VaultStorage>> -   _deprecated_swapTokens: address[] <<VaultStorage>> -Internal: -   assets: mapping(address=>Asset) <<VaultStorage>> -   allAssets: address[] <<VaultStorage>> -   strategies: mapping(address=>Strategy) <<VaultStorage>> -   allStrategies: address[] <<VaultStorage>> -   oUSD: OUSD <<VaultStorage>> -   swapConfig: SwapConfig <<VaultStorage>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   priceProvider: address <<VaultStorage>> -   rebasePaused: bool <<VaultStorage>> -   capitalPaused: bool <<VaultStorage>> -   redeemFeeBps: uint256 <<VaultStorage>> -   vaultBuffer: uint256 <<VaultStorage>> -   autoAllocateThreshold: uint256 <<VaultStorage>> -   rebaseThreshold: uint256 <<VaultStorage>> -   adminImplPosition: bytes32 <<VaultStorage>> -   strategistAddr: address <<VaultStorage>> -   assetDefaultStrategies: mapping(address=>address) <<VaultStorage>> -   maxSupplyDiff: uint256 <<VaultStorage>> -   trusteeAddress: address <<VaultStorage>> -   trusteeFeeBps: uint256 <<VaultStorage>> -   MINT_MINIMUM_UNIT_PRICE: uint256 <<VaultStorage>> -   ousdMetaStrategy: address <<VaultStorage>> -   netOusdMintedForStrategy: int256 <<VaultStorage>> -   netOusdMintForStrategyThreshold: uint256 <<VaultStorage>> -   MIN_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> -   MAX_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> - -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _postSwapChecks(_fromAsset: address, _fromAssetAmount: uint256, fromAssetConfig: Asset, _toAsset: address, toAssetAmount: uint256, _minToAssetAmount: uint256, toAssetConfig: Asset, config: SwapConfig) <<VaultAdmin>> -    _depositToStrategy(_strategyToAddress: address, _assets: address[], _amounts: uint256[]) <<VaultAdmin>> -    _withdrawFromStrategy(_recipient: address, _strategyFromAddress: address, _assets: address[], _amounts: uint256[]) <<VaultAdmin>> -    _cacheDecimals(token: address) <<VaultAdmin>> -External: -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    setAdminImpl(newImpl: address) <<onlyGovernor>> <<VaultStorage>> -    setPriceProvider(_priceProvider: address) <<onlyGovernor>> <<VaultAdmin>> -    setRedeemFeeBps(_redeemFeeBps: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setVaultBuffer(_vaultBuffer: uint256) <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    setAutoAllocateThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setRebaseThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setStrategistAddr(_address: address) <<onlyGovernor>> <<VaultAdmin>> -    setAssetDefaultStrategy(_asset: address, _strategy: address) <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    setNetOusdMintForStrategyThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> -    swapCollateral(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _minToAssetAmount: uint256, _data: bytes): (toAssetAmount: uint256) <<nonReentrant, onlyGovernorOrStrategist>> <<VaultAdmin>> -    setSwapper(_swapperAddr: address) <<onlyGovernor>> <<VaultAdmin>> -    swapper(): (swapper_: address) <<VaultAdmin>> -    setSwapAllowedUndervalue(_basis: uint16) <<onlyGovernor>> <<VaultAdmin>> -    allowedSwapUndervalue(): (value: uint256) <<VaultAdmin>> -    setOracleSlippage(_asset: address, _allowedOracleSlippageBps: uint16) <<onlyGovernor>> <<VaultAdmin>> -    supportAsset(_asset: address, _unitConversion: uint8) <<onlyGovernor>> <<VaultAdmin>> -    cacheDecimals(_asset: address) <<onlyGovernor>> <<VaultAdmin>> -    approveStrategy(_addr: address) <<onlyGovernor>> <<VaultAdmin>> -    removeStrategy(_addr: address) <<onlyGovernor>> <<VaultAdmin>> -    depositToStrategy(_strategyToAddress: address, _assets: address[], _amounts: uint256[]) <<onlyGovernorOrStrategist, nonReentrant>> <<VaultAdmin>> -    withdrawFromStrategy(_strategyFromAddress: address, _assets: address[], _amounts: uint256[]) <<onlyGovernorOrStrategist, nonReentrant>> <<VaultAdmin>> -    setMaxSupplyDiff(_maxSupplyDiff: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setTrusteeAddress(_address: address) <<onlyGovernor>> <<VaultAdmin>> -    setTrusteeFeeBps(_basis: uint256) <<onlyGovernor>> <<VaultAdmin>> -    setOusdMetaStrategy(_ousdMetaStrategy: address) <<onlyGovernor>> <<VaultAdmin>> -    pauseRebase() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    unpauseRebase() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    pauseCapital() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    unpauseCapital() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<VaultAdmin>> -    withdrawAllFromStrategy(_strategyAddr: address) <<onlyGovernorOrStrategist>> <<VaultAdmin>> -    withdrawAllFromStrategies() <<onlyGovernorOrStrategist>> <<VaultAdmin>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> AssetSupported(_asset: address) <<VaultStorage>> -    <<event>> AssetDefaultStrategyUpdated(_asset: address, _strategy: address) <<VaultStorage>> -    <<event>> AssetAllocated(_asset: address, _strategy: address, _amount: uint256) <<VaultStorage>> -    <<event>> StrategyApproved(_addr: address) <<VaultStorage>> -    <<event>> StrategyRemoved(_addr: address) <<VaultStorage>> -    <<event>> Mint(_addr: address, _value: uint256) <<VaultStorage>> -    <<event>> Redeem(_addr: address, _value: uint256) <<VaultStorage>> -    <<event>> CapitalPaused() <<VaultStorage>> -    <<event>> CapitalUnpaused() <<VaultStorage>> -    <<event>> RebasePaused() <<VaultStorage>> -    <<event>> RebaseUnpaused() <<VaultStorage>> -    <<event>> VaultBufferUpdated(_vaultBuffer: uint256) <<VaultStorage>> -    <<event>> OusdMetaStrategyUpdated(_ousdMetaStrategy: address) <<VaultStorage>> -    <<event>> RedeemFeeUpdated(_redeemFeeBps: uint256) <<VaultStorage>> -    <<event>> PriceProviderUpdated(_priceProvider: address) <<VaultStorage>> -    <<event>> AllocateThresholdUpdated(_threshold: uint256) <<VaultStorage>> -    <<event>> RebaseThresholdUpdated(_threshold: uint256) <<VaultStorage>> -    <<event>> StrategistUpdated(_address: address) <<VaultStorage>> -    <<event>> MaxSupplyDiffChanged(maxSupplyDiff: uint256) <<VaultStorage>> -    <<event>> YieldDistribution(_to: address, _yield: uint256, _fee: uint256) <<VaultStorage>> -    <<event>> TrusteeFeeBpsChanged(_basis: uint256) <<VaultStorage>> -    <<event>> TrusteeAddressChanged(_address: address) <<VaultStorage>> -    <<event>> NetOusdMintForStrategyThresholdChanged(_threshold: uint256) <<VaultStorage>> -    <<event>> SwapperChanged(_address: address) <<VaultStorage>> -    <<event>> SwapAllowedUndervalueChanged(_basis: uint256) <<VaultStorage>> -    <<event>> SwapSlippageChanged(_asset: address, _basis: uint256) <<VaultStorage>> -    <<event>> Swapped(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _toAssetAmount: uint256) <<VaultStorage>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> nonReentrantView() <<Governable>> +179 + +VaultAdmin +../contracts/vault/VaultAdmin.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_rebaseHooksAddr: address <<VaultStorage>> +   _deprecated_uniswapAddr: address <<VaultStorage>> +   _deprecated_swapTokens: address[] <<VaultStorage>> +Internal: +   assets: mapping(address=>Asset) <<VaultStorage>> +   allAssets: address[] <<VaultStorage>> +   strategies: mapping(address=>Strategy) <<VaultStorage>> +   allStrategies: address[] <<VaultStorage>> +   oUSD: OUSD <<VaultStorage>> +   swapConfig: SwapConfig <<VaultStorage>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   priceProvider: address <<VaultStorage>> +   rebasePaused: bool <<VaultStorage>> +   capitalPaused: bool <<VaultStorage>> +   redeemFeeBps: uint256 <<VaultStorage>> +   vaultBuffer: uint256 <<VaultStorage>> +   autoAllocateThreshold: uint256 <<VaultStorage>> +   rebaseThreshold: uint256 <<VaultStorage>> +   adminImplPosition: bytes32 <<VaultStorage>> +   strategistAddr: address <<VaultStorage>> +   assetDefaultStrategies: mapping(address=>address) <<VaultStorage>> +   maxSupplyDiff: uint256 <<VaultStorage>> +   trusteeAddress: address <<VaultStorage>> +   trusteeFeeBps: uint256 <<VaultStorage>> +   MINT_MINIMUM_UNIT_PRICE: uint256 <<VaultStorage>> +   ousdMetaStrategy: address <<VaultStorage>> +   netOusdMintedForStrategy: int256 <<VaultStorage>> +   netOusdMintForStrategyThreshold: uint256 <<VaultStorage>> +   MIN_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> +   MAX_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _depositToStrategy(_strategyToAddress: address, _assets: address[], _amounts: uint256[]) <<VaultAdmin>> +    _withdrawFromStrategy(_recipient: address, _strategyFromAddress: address, _assets: address[], _amounts: uint256[]) <<VaultAdmin>> +    _cacheDecimals(token: address) <<VaultAdmin>> +External: +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    setAdminImpl(newImpl: address) <<onlyGovernor>> <<VaultStorage>> +    setPriceProvider(_priceProvider: address) <<onlyGovernor>> <<VaultAdmin>> +    setRedeemFeeBps(_redeemFeeBps: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setVaultBuffer(_vaultBuffer: uint256) <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    setAutoAllocateThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setRebaseThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setStrategistAddr(_address: address) <<onlyGovernor>> <<VaultAdmin>> +    setAssetDefaultStrategy(_asset: address, _strategy: address) <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    setNetOusdMintForStrategyThreshold(_threshold: uint256) <<onlyGovernor>> <<VaultAdmin>> +    swapCollateral(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _minToAssetAmount: uint256, _data: bytes): (toAssetAmount: uint256) <<nonReentrant, onlyGovernorOrStrategist>> <<VaultAdmin>> +    setSwapper(_swapperAddr: address) <<onlyGovernor>> <<VaultAdmin>> +    swapper(): (swapper_: address) <<VaultAdmin>> +    setSwapAllowedUndervalue(_basis: uint16) <<onlyGovernor>> <<VaultAdmin>> +    allowedSwapUndervalue(): (value: uint256) <<VaultAdmin>> +    setOracleSlippage(_asset: address, _allowedOracleSlippageBps: uint16) <<onlyGovernor>> <<VaultAdmin>> +    supportAsset(_asset: address, _unitConversion: uint8) <<onlyGovernor>> <<VaultAdmin>> +    cacheDecimals(_asset: address) <<onlyGovernor>> <<VaultAdmin>> +    approveStrategy(_addr: address) <<onlyGovernor>> <<VaultAdmin>> +    removeStrategy(_addr: address) <<onlyGovernor>> <<VaultAdmin>> +    depositToStrategy(_strategyToAddress: address, _assets: address[], _amounts: uint256[]) <<onlyGovernorOrStrategist, nonReentrant>> <<VaultAdmin>> +    withdrawFromStrategy(_strategyFromAddress: address, _assets: address[], _amounts: uint256[]) <<onlyGovernorOrStrategist, nonReentrant>> <<VaultAdmin>> +    setMaxSupplyDiff(_maxSupplyDiff: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setTrusteeAddress(_address: address) <<onlyGovernor>> <<VaultAdmin>> +    setTrusteeFeeBps(_basis: uint256) <<onlyGovernor>> <<VaultAdmin>> +    setOusdMetaStrategy(_ousdMetaStrategy: address) <<onlyGovernor>> <<VaultAdmin>> +    pauseRebase() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    unpauseRebase() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    pauseCapital() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    unpauseCapital() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    transferToken(_asset: address, _amount: uint256) <<onlyGovernor>> <<VaultAdmin>> +    withdrawAllFromStrategy(_strategyAddr: address) <<onlyGovernorOrStrategist>> <<VaultAdmin>> +    withdrawAllFromStrategies() <<onlyGovernorOrStrategist>> <<VaultAdmin>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> AssetSupported(_asset: address) <<VaultStorage>> +    <<event>> AssetDefaultStrategyUpdated(_asset: address, _strategy: address) <<VaultStorage>> +    <<event>> AssetAllocated(_asset: address, _strategy: address, _amount: uint256) <<VaultStorage>> +    <<event>> StrategyApproved(_addr: address) <<VaultStorage>> +    <<event>> StrategyRemoved(_addr: address) <<VaultStorage>> +    <<event>> Mint(_addr: address, _value: uint256) <<VaultStorage>> +    <<event>> Redeem(_addr: address, _value: uint256) <<VaultStorage>> +    <<event>> CapitalPaused() <<VaultStorage>> +    <<event>> CapitalUnpaused() <<VaultStorage>> +    <<event>> RebasePaused() <<VaultStorage>> +    <<event>> RebaseUnpaused() <<VaultStorage>> +    <<event>> VaultBufferUpdated(_vaultBuffer: uint256) <<VaultStorage>> +    <<event>> OusdMetaStrategyUpdated(_ousdMetaStrategy: address) <<VaultStorage>> +    <<event>> RedeemFeeUpdated(_redeemFeeBps: uint256) <<VaultStorage>> +    <<event>> PriceProviderUpdated(_priceProvider: address) <<VaultStorage>> +    <<event>> AllocateThresholdUpdated(_threshold: uint256) <<VaultStorage>> +    <<event>> RebaseThresholdUpdated(_threshold: uint256) <<VaultStorage>> +    <<event>> StrategistUpdated(_address: address) <<VaultStorage>> +    <<event>> MaxSupplyDiffChanged(maxSupplyDiff: uint256) <<VaultStorage>> +    <<event>> YieldDistribution(_to: address, _yield: uint256, _fee: uint256) <<VaultStorage>> +    <<event>> TrusteeFeeBpsChanged(_basis: uint256) <<VaultStorage>> +    <<event>> TrusteeAddressChanged(_address: address) <<VaultStorage>> +    <<event>> NetOusdMintForStrategyThresholdChanged(_threshold: uint256) <<VaultStorage>> +    <<event>> SwapperChanged(_address: address) <<VaultStorage>> +    <<event>> SwapAllowedUndervalueChanged(_basis: uint256) <<VaultStorage>> +    <<event>> SwapSlippageChanged(_asset: address, _basis: uint256) <<VaultStorage>> +    <<event>> Swapped(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _toAssetAmount: uint256) <<VaultStorage>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>>    <<modifier>> onlyGovernorOrStrategist() <<VaultAdmin>>    constructor() <<Governable>>    governor(): address <<Governable>> diff --git a/contracts/docs/VaultCoreSquashed.svg b/contracts/docs/VaultCoreSquashed.svg index 0f1c66b862..26df81e4b3 100644 --- a/contracts/docs/VaultCoreSquashed.svg +++ b/contracts/docs/VaultCoreSquashed.svg @@ -4,137 +4,136 @@ - - + + UmlClassDiagram - - + + -174 - -VaultCore -../contracts/vault/VaultCore.sol - -Private: -   initialized: bool <<Initializable>> -   initializing: bool <<Initializable>> -   ______gap: uint256[50] <<Initializable>> -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -   _deprecated_rebaseHooksAddr: address <<VaultStorage>> -   _deprecated_uniswapAddr: address <<VaultStorage>> -   _deprecated_swapTokens: address[] <<VaultStorage>> -Internal: -   assets: mapping(address=>Asset) <<VaultStorage>> -   allAssets: address[] <<VaultStorage>> -   strategies: mapping(address=>Strategy) <<VaultStorage>> -   allStrategies: address[] <<VaultStorage>> -   oUSD: OUSD <<VaultStorage>> -   swapConfig: SwapConfig <<VaultStorage>> -   MAX_INT: uint256 <<VaultCore>> -   MAX_UINT: uint256 <<VaultCore>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   priceProvider: address <<VaultStorage>> -   rebasePaused: bool <<VaultStorage>> -   capitalPaused: bool <<VaultStorage>> -   redeemFeeBps: uint256 <<VaultStorage>> -   vaultBuffer: uint256 <<VaultStorage>> -   autoAllocateThreshold: uint256 <<VaultStorage>> -   rebaseThreshold: uint256 <<VaultStorage>> -   adminImplPosition: bytes32 <<VaultStorage>> -   strategistAddr: address <<VaultStorage>> -   assetDefaultStrategies: mapping(address=>address) <<VaultStorage>> -   maxSupplyDiff: uint256 <<VaultStorage>> -   trusteeAddress: address <<VaultStorage>> -   trusteeFeeBps: uint256 <<VaultStorage>> -   MINT_MINIMUM_UNIT_PRICE: uint256 <<VaultStorage>> -   ousdMetaStrategy: address <<VaultStorage>> -   netOusdMintedForStrategy: int256 <<VaultStorage>> -   netOusdMintForStrategyThreshold: uint256 <<VaultStorage>> -   MIN_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> -   MAX_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> - -Private: -    abs(x: int256): uint256 <<VaultCore>> -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _redeem(_amount: uint256, _minimumUnitAmount: uint256) <<VaultCore>> -    _allocate() <<VaultCore>> -    _rebase(): uint256 <<whenNotRebasePaused>> <<VaultCore>> -    _totalValue(): (value: uint256) <<VaultCore>> -    _totalValueInVault(): (value: uint256) <<VaultCore>> -    _totalValueInStrategies(): (value: uint256) <<VaultCore>> -    _totalValueInStrategy(_strategyAddr: address): (value: uint256) <<VaultCore>> -    _checkBalance(_asset: address): (balance: uint256) <<VaultCore>> -    _calculateRedeemOutputs(_amount: uint256): (outputs: uint256[]) <<VaultCore>> -    _toUnits(_raw: uint256, _asset: address): uint256 <<VaultCore>> -    _toUnitPrice(_asset: address, isMint: bool): (price: uint256) <<VaultCore>> -    _getDecimals(_asset: address): (decimals: uint256) <<VaultCore>> -External: -    <<payable>> null() <<VaultCore>> -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    setAdminImpl(newImpl: address) <<onlyGovernor>> <<VaultStorage>> -    mint(_asset: address, _amount: uint256, _minimumOusdAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> -    mintForStrategy(_amount: uint256) <<whenNotCapitalPaused, onlyOusdMetaStrategy>> <<VaultCore>> -    redeem(_amount: uint256, _minimumUnitAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> -    burnForStrategy(_amount: uint256) <<whenNotCapitalPaused, onlyOusdMetaStrategy>> <<VaultCore>> -    redeemAll(_minimumUnitAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> -    allocate() <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> -    rebase() <<nonReentrant>> <<VaultCore>> -    totalValue(): (value: uint256) <<VaultCore>> -    checkBalance(_asset: address): uint256 <<VaultCore>> -    calculateRedeemOutputs(_amount: uint256): uint256[] <<VaultCore>> -    priceUnitMint(asset: address): (price: uint256) <<VaultCore>> -    priceUnitRedeem(asset: address): (price: uint256) <<VaultCore>> -    getAllAssets(): address[] <<VaultCore>> -    getStrategyCount(): uint256 <<VaultCore>> -    getAllStrategies(): address[] <<VaultCore>> -    isSupportedAsset(_asset: address): bool <<VaultCore>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> AssetSupported(_asset: address) <<VaultStorage>> -    <<event>> AssetDefaultStrategyUpdated(_asset: address, _strategy: address) <<VaultStorage>> -    <<event>> AssetAllocated(_asset: address, _strategy: address, _amount: uint256) <<VaultStorage>> -    <<event>> StrategyApproved(_addr: address) <<VaultStorage>> -    <<event>> StrategyRemoved(_addr: address) <<VaultStorage>> -    <<event>> Mint(_addr: address, _value: uint256) <<VaultStorage>> -    <<event>> Redeem(_addr: address, _value: uint256) <<VaultStorage>> -    <<event>> CapitalPaused() <<VaultStorage>> -    <<event>> CapitalUnpaused() <<VaultStorage>> -    <<event>> RebasePaused() <<VaultStorage>> -    <<event>> RebaseUnpaused() <<VaultStorage>> -    <<event>> VaultBufferUpdated(_vaultBuffer: uint256) <<VaultStorage>> -    <<event>> OusdMetaStrategyUpdated(_ousdMetaStrategy: address) <<VaultStorage>> -    <<event>> RedeemFeeUpdated(_redeemFeeBps: uint256) <<VaultStorage>> -    <<event>> PriceProviderUpdated(_priceProvider: address) <<VaultStorage>> -    <<event>> AllocateThresholdUpdated(_threshold: uint256) <<VaultStorage>> -    <<event>> RebaseThresholdUpdated(_threshold: uint256) <<VaultStorage>> -    <<event>> StrategistUpdated(_address: address) <<VaultStorage>> -    <<event>> MaxSupplyDiffChanged(maxSupplyDiff: uint256) <<VaultStorage>> -    <<event>> YieldDistribution(_to: address, _yield: uint256, _fee: uint256) <<VaultStorage>> -    <<event>> TrusteeFeeBpsChanged(_basis: uint256) <<VaultStorage>> -    <<event>> TrusteeAddressChanged(_address: address) <<VaultStorage>> -    <<event>> NetOusdMintForStrategyThresholdChanged(_threshold: uint256) <<VaultStorage>> -    <<event>> SwapperChanged(_address: address) <<VaultStorage>> -    <<event>> SwapAllowedUndervalueChanged(_basis: uint256) <<VaultStorage>> -    <<event>> SwapSlippageChanged(_asset: address, _basis: uint256) <<VaultStorage>> -    <<event>> Swapped(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _toAssetAmount: uint256) <<VaultStorage>> -    <<modifier>> initializer() <<Initializable>> -    <<modifier>> onlyGovernor() <<Governable>> -    <<modifier>> nonReentrant() <<Governable>> -    <<modifier>> nonReentrantView() <<Governable>> -    <<modifier>> whenNotCapitalPaused() <<VaultCore>> -    <<modifier>> whenNotRebasePaused() <<VaultCore>> +180 + +VaultCore +../contracts/vault/VaultCore.sol + +Private: +   initialized: bool <<Initializable>> +   initializing: bool <<Initializable>> +   ______gap: uint256[50] <<Initializable>> +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +   _deprecated_rebaseHooksAddr: address <<VaultStorage>> +   _deprecated_uniswapAddr: address <<VaultStorage>> +   _deprecated_swapTokens: address[] <<VaultStorage>> +Internal: +   assets: mapping(address=>Asset) <<VaultStorage>> +   allAssets: address[] <<VaultStorage>> +   strategies: mapping(address=>Strategy) <<VaultStorage>> +   allStrategies: address[] <<VaultStorage>> +   oUSD: OUSD <<VaultStorage>> +   swapConfig: SwapConfig <<VaultStorage>> +   MAX_INT: uint256 <<VaultCore>> +   MAX_UINT: uint256 <<VaultCore>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   priceProvider: address <<VaultStorage>> +   rebasePaused: bool <<VaultStorage>> +   capitalPaused: bool <<VaultStorage>> +   redeemFeeBps: uint256 <<VaultStorage>> +   vaultBuffer: uint256 <<VaultStorage>> +   autoAllocateThreshold: uint256 <<VaultStorage>> +   rebaseThreshold: uint256 <<VaultStorage>> +   adminImplPosition: bytes32 <<VaultStorage>> +   strategistAddr: address <<VaultStorage>> +   assetDefaultStrategies: mapping(address=>address) <<VaultStorage>> +   maxSupplyDiff: uint256 <<VaultStorage>> +   trusteeAddress: address <<VaultStorage>> +   trusteeFeeBps: uint256 <<VaultStorage>> +   MINT_MINIMUM_UNIT_PRICE: uint256 <<VaultStorage>> +   ousdMetaStrategy: address <<VaultStorage>> +   netOusdMintedForStrategy: int256 <<VaultStorage>> +   netOusdMintForStrategyThreshold: uint256 <<VaultStorage>> +   MIN_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> +   MAX_UNIT_PRICE_DRIFT: uint256 <<VaultStorage>> + +Private: +    abs(x: int256): uint256 <<VaultCore>> +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _redeem(_amount: uint256, _minimumUnitAmount: uint256) <<VaultCore>> +    _allocate() <<VaultCore>> +    _rebase(): uint256 <<whenNotRebasePaused>> <<VaultCore>> +    _totalValue(): (value: uint256) <<VaultCore>> +    _totalValueInVault(): (value: uint256) <<VaultCore>> +    _totalValueInStrategies(): (value: uint256) <<VaultCore>> +    _totalValueInStrategy(_strategyAddr: address): (value: uint256) <<VaultCore>> +    _checkBalance(_asset: address): (balance: uint256) <<VaultCore>> +    _calculateRedeemOutputs(_amount: uint256): (outputs: uint256[]) <<VaultCore>> +    _toUnits(_raw: uint256, _asset: address): uint256 <<VaultCore>> +    _toUnitPrice(_asset: address, isMint: bool): (price: uint256) <<VaultCore>> +    _getDecimals(_asset: address): (decimals: uint256) <<VaultCore>> +External: +    <<payable>> null() <<VaultCore>> +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    setAdminImpl(newImpl: address) <<onlyGovernor>> <<VaultStorage>> +    mint(_asset: address, _amount: uint256, _minimumOusdAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> +    mintForStrategy(_amount: uint256) <<whenNotCapitalPaused, onlyOusdMetaStrategy>> <<VaultCore>> +    redeem(_amount: uint256, _minimumUnitAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> +    burnForStrategy(_amount: uint256) <<whenNotCapitalPaused, onlyOusdMetaStrategy>> <<VaultCore>> +    redeemAll(_minimumUnitAmount: uint256) <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> +    allocate() <<whenNotCapitalPaused, nonReentrant>> <<VaultCore>> +    rebase() <<nonReentrant>> <<VaultCore>> +    totalValue(): (value: uint256) <<VaultCore>> +    checkBalance(_asset: address): uint256 <<VaultCore>> +    calculateRedeemOutputs(_amount: uint256): uint256[] <<VaultCore>> +    priceUnitMint(asset: address): (price: uint256) <<VaultCore>> +    priceUnitRedeem(asset: address): (price: uint256) <<VaultCore>> +    getAllAssets(): address[] <<VaultCore>> +    getStrategyCount(): uint256 <<VaultCore>> +    getAllStrategies(): address[] <<VaultCore>> +    isSupportedAsset(_asset: address): bool <<VaultCore>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> AssetSupported(_asset: address) <<VaultStorage>> +    <<event>> AssetDefaultStrategyUpdated(_asset: address, _strategy: address) <<VaultStorage>> +    <<event>> AssetAllocated(_asset: address, _strategy: address, _amount: uint256) <<VaultStorage>> +    <<event>> StrategyApproved(_addr: address) <<VaultStorage>> +    <<event>> StrategyRemoved(_addr: address) <<VaultStorage>> +    <<event>> Mint(_addr: address, _value: uint256) <<VaultStorage>> +    <<event>> Redeem(_addr: address, _value: uint256) <<VaultStorage>> +    <<event>> CapitalPaused() <<VaultStorage>> +    <<event>> CapitalUnpaused() <<VaultStorage>> +    <<event>> RebasePaused() <<VaultStorage>> +    <<event>> RebaseUnpaused() <<VaultStorage>> +    <<event>> VaultBufferUpdated(_vaultBuffer: uint256) <<VaultStorage>> +    <<event>> OusdMetaStrategyUpdated(_ousdMetaStrategy: address) <<VaultStorage>> +    <<event>> RedeemFeeUpdated(_redeemFeeBps: uint256) <<VaultStorage>> +    <<event>> PriceProviderUpdated(_priceProvider: address) <<VaultStorage>> +    <<event>> AllocateThresholdUpdated(_threshold: uint256) <<VaultStorage>> +    <<event>> RebaseThresholdUpdated(_threshold: uint256) <<VaultStorage>> +    <<event>> StrategistUpdated(_address: address) <<VaultStorage>> +    <<event>> MaxSupplyDiffChanged(maxSupplyDiff: uint256) <<VaultStorage>> +    <<event>> YieldDistribution(_to: address, _yield: uint256, _fee: uint256) <<VaultStorage>> +    <<event>> TrusteeFeeBpsChanged(_basis: uint256) <<VaultStorage>> +    <<event>> TrusteeAddressChanged(_address: address) <<VaultStorage>> +    <<event>> NetOusdMintForStrategyThresholdChanged(_threshold: uint256) <<VaultStorage>> +    <<event>> SwapperChanged(_address: address) <<VaultStorage>> +    <<event>> SwapAllowedUndervalueChanged(_basis: uint256) <<VaultStorage>> +    <<event>> SwapSlippageChanged(_asset: address, _basis: uint256) <<VaultStorage>> +    <<event>> Swapped(_fromAsset: address, _toAsset: address, _fromAssetAmount: uint256, _toAssetAmount: uint256) <<VaultStorage>> +    <<modifier>> initializer() <<Initializable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    <<modifier>> whenNotRebasePaused() <<VaultCore>> +    <<modifier>> whenNotCapitalPaused() <<VaultCore>>    <<modifier>> onlyOusdMetaStrategy() <<VaultCore>>    constructor() <<Governable>>    governor(): address <<Governable>> diff --git a/contracts/docs/VaultHierarchy.svg b/contracts/docs/VaultHierarchy.svg index b5d37bae5d..3a742d35a7 100644 --- a/contracts/docs/VaultHierarchy.svg +++ b/contracts/docs/VaultHierarchy.svg @@ -16,209 +16,209 @@ Governable ../contracts/governance/Governable.sol - + -26 +27 <<Interface>> IGetExchangeRateToken ../contracts/interfaces/IGetExchangeRateToken.sol - + -34 +35 <<Interface>> IOracle ../contracts/interfaces/IOracle.sol - + -37 +39 <<Interface>> IStrategy ../contracts/interfaces/IStrategy.sol - + -38 +40 <<Interface>> ISwapper ../contracts/interfaces/ISwapper.sol - + -40 +42 <<Interface>> IVault ../contracts/interfaces/IVault.sol - + -176 +182 VaultStorage ../contracts/vault/VaultStorage.sol - + -40->176 +42->182 - + -157 +161 OUSD ../contracts/token/OUSD.sol - + -157->7 +161->7 - + -164 +169 <<Abstract>> Initializable ../contracts/utils/Initializable.sol - + -157->164 +161->169 - + -166 +172 <<Abstract>> InitializableERC20Detailed ../contracts/utils/InitializableERC20Detailed.sol - + -157->166 +161->172 - + -338 +358 <<Interface>> IERC20 ../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - + -166->338 +172->358 - + -173 +179 VaultAdmin ../contracts/vault/VaultAdmin.sol - + -173->34 +179->35 - + -173->37 +179->39 - + -173->38 +179->40 - + -173->40 +179->42 - + -173->176 +179->182 - + -173->338 +179->358 - + -174 +180 VaultCore ../contracts/vault/VaultCore.sol - + -174->26 +180->27 - + -174->34 +180->35 - + -174->37 +180->39 - + -174->176 +180->182 - + -174->338 +180->358 - + -176->7 +182->7 - + -176->157 +182->161 - + -176->164 +182->169 diff --git a/contracts/docs/generate.sh b/contracts/docs/generate.sh index 2c0d7283f8..41ca253692 100644 --- a/contracts/docs/generate.sh +++ b/contracts/docs/generate.sh @@ -67,6 +67,11 @@ sol2uml .. -v -hv -hf -he -hs -hl -b MorphoCompoundStrategy -o MorphoCompStrateg sol2uml .. -s -d 0 -b MorphoCompoundStrategy -o MorphoCompStrategySquashed.svg sol2uml storage .. -c MorphoCompoundStrategy -o MorphoCompStrategyStorage.svg +# contracts/strategies/balancer +sol2uml .. -v -hv -hf -he -hs -hl -b BalancerMetaPoolStrategy -o BalancerMetaPoolStrategyHierarchy.svg +sol2uml .. -s -d 0 -b BalancerMetaPoolStrategy -o BalancerMetaPoolStrategySquashed.svg +sol2uml storage .. -c BalancerMetaPoolStrategy -o BalancerMetaPoolStrategyStorage.svg + # contracts/swapper sol2uml .. -v -hv -hf -he -hs -hl -b Swapper1InchV5 -o Swapper1InchV5Hierarchy.svg sol2uml .. -s -d 0 -b Swapper1InchV5 -o Swapper1InchV5Squashed.svg diff --git a/contracts/docs/plantuml/oethContracts.png b/contracts/docs/plantuml/oethContracts.png index 2ec7b8c510f464a75d37ef2ddeda3d8abf14ad38..bee23ce3d674c06c108cd08b8600243f3883c4ba 100644 GIT binary patch literal 68878 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 z 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 Q7Vx7erz%?_ZQ}p`01W$Dp#T5? literal 57821 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 dn)4&JNOfaaqAwl0Q@xRcZ4Lbk; diff --git a/contracts/docs/plantuml/oethContracts.puml b/contracts/docs/plantuml/oethContracts.puml index ce6e98f67c..3d14c9cdf4 100644 --- a/contracts/docs/plantuml/oethContracts.puml +++ b/contracts/docs/plantuml/oethContracts.puml @@ -37,7 +37,7 @@ object "Swapper1InchV5" as swap <> #DeepSkyBlue { } object "OETHHarvester" as harv <><> #DeepSkyBlue { - rewards: CRV, CVX + rewards: CRV, CVX, BAL, AURA } ' Strategies @@ -49,12 +49,19 @@ object "ConvexEthMetaStrategy" as cvxStrat <><> #DeepSkyBlue { asset: WETH Curve metapool: OETHCRV-f Convex pool: cvxOETHCRV-f + Rewards: CRV, CVX } object "MorphoAaveStrategy" as morphAaveStrat <><> #DeepSkyBlue { asset: WETH Aave token: aWETH } +object "BalancerMetaPoolStrategy" as balancerStrat <><> #DeepSkyBlue { + asset: rETH, WETH + Balancer Pool Token: B-rETH-STABLE + Rewards: BAL, AURA +} + ' Oracle object "OETHOracleRouter" as oracle <> #DeepSkyBlue { pairs: @@ -202,6 +209,11 @@ oeth <... morphAaveStrat ' morphoV2 ..> aweth ' morphoV2 ..> vdweth +' Balancer Strategy +oethv <...> balancerStrat +oeth <... balancerStrat +harv <..> balancerStrat + ' ' Vault to Assets ' oethv .....> frxeth ' oethv .....> weth diff --git a/contracts/package.json b/contracts/package.json index 121912cf5b..f36c5fbc1f 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -11,7 +11,7 @@ "node": "yarn run node:fork", "node:fork": "./node.sh fork", "lint": "yarn run lint:js && yarn run lint:sol", - "lint:js": "eslint \"test/**/*.js\"", + "lint:js": "eslint \"test/**/*.js\" \"tasks/**/*.js\"", "lint:sol": "solhint \"contracts/**/*.sol\"", "prettier": "yarn run prettier:js && yarn run prettier:sol", "prettier:check": "prettier -c \"*.js\" \"deploy/**/*.js\" \"scripts/**/*.js\" \"smoke/**/*.js\" \"scripts/**/*.js\" \"tasks/**/*.js\" \"test/**/*.js\" \"utils/**/*.js\"", diff --git a/contracts/tasks/account.js b/contracts/tasks/account.js index b8aad185d7..bbd2494f63 100644 --- a/contracts/tasks/account.js +++ b/contracts/tasks/account.js @@ -1,5 +1,3 @@ -const _ = require("lodash"); - // USDT has its own ABI because of non standard returns const usdtAbi = require("../test/abi/usdt.json").abi; const daiAbi = require("../test/abi/erc20.json"); @@ -55,7 +53,6 @@ async function fund(taskArguments, hre) { usdtUnits, daiUnits, usdcUnits, - tusdUnits, isFork, isLocalhost, } = require("../test/helpers"); @@ -178,7 +175,7 @@ async function fund(taskArguments, hre) { */ async function mint(taskArguments, hre) { const addresses = require("../utils/addresses"); - const { usdtUnits, isFork, isLocalhost } = require("../test/helpers"); + const { usdtUnits, isFork } = require("../test/helpers"); if (!isFork) { throw new Error("Task can only be used on fork"); @@ -252,7 +249,6 @@ async function redeemFor(taskArguments, hre) { usdcUnitsFormat, usdtUnitsFormat, isFork, - isLocalhost, } = require("../test/helpers"); if (!isFork) { diff --git a/contracts/tasks/curve.js b/contracts/tasks/curve.js index 3b646f0888..09c15a507a 100644 --- a/contracts/tasks/curve.js +++ b/contracts/tasks/curve.js @@ -212,12 +212,15 @@ async function curvePool(taskArguments, hre) { // Strategies assets value const strategyAssetsValueBefore = diffBlocks && - (await amoStrategy.checkBalance(asset.address, { + (await amoStrategy["checkBalance(address)"](asset.address, { blockTag: fromBlockTag, })); - const strategyAssetsValue = await amoStrategy.checkBalance(asset.address, { - blockTag, - }); + const strategyAssetsValue = await amoStrategy["checkBalance(address)"]( + asset.address, + { + blockTag, + } + ); console.log( `strategy assets value : ${displayPortion( strategyAssetsValue, diff --git a/contracts/tasks/smokeTest.js b/contracts/tasks/smokeTest.js index 35f4bc02e5..0b57d87e55 100644 --- a/contracts/tasks/smokeTest.js +++ b/contracts/tasks/smokeTest.js @@ -8,11 +8,7 @@ * param receives return value of `beforeDeploy` function. `beforeDeployData` can be used to validate * that the state change is ok */ -const { - getDeployScripts, - getLastDeployScript, - getFilesInFolder, -} = require("../utils/fileSystem"); +const { getDeployScripts, getFilesInFolder } = require("../utils/fileSystem"); const readline = require("readline"); readline.emitKeypressEvents(process.stdin); @@ -51,7 +47,7 @@ function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } -async function smokeTestCheck(taskArguments, hre) { +async function smokeTestCheck(taskArguments) { const deployId = taskArguments.deployid; if (!deployId) { diff --git a/contracts/tasks/storageSlots.js b/contracts/tasks/storageSlots.js index d82a76472e..7462d3fa69 100644 --- a/contracts/tasks/storageSlots.js +++ b/contracts/tasks/storageSlots.js @@ -256,7 +256,7 @@ const enrichLayoutData = (layout) => { } else { const fixedArraySize = parseInt(arrayType); sItem.bits = [...Array(fixedArraySize).keys()].map( - (_) => itemToBytesMap[itemType] + () => itemToBytesMap[itemType] ); } } else if (mappingRegex.test(sItem.type)) { @@ -284,7 +284,7 @@ const enrichLayoutData = (layout) => { let currentSlot = 0; let currentSlotBits = 0; // assign slots to mappings - layout.storage = layout.storage.map((sItem, i) => { + layout.storage = layout.storage.map((sItem) => { // current slot is not empty and new slot is required if (sItem.newSlot && currentSlotBits !== 0) { currentSlot += 1; diff --git a/contracts/tasks/tasks.js b/contracts/tasks/tasks.js index 2610653e68..3f832d7628 100644 --- a/contracts/tasks/tasks.js +++ b/contracts/tasks/tasks.js @@ -20,7 +20,7 @@ const { checkOUSDBalances, supplyStakingContractWithOGN, } = require("./compensation"); -const { allocate, capital, harvest, rebase, yield } = require("./vault"); +const { allocate, capital, harvest, rebase, yieldTask } = require("./vault"); const { curvePool } = require("./curve"); // Environment tasks. @@ -69,7 +69,7 @@ task("allocate", "Call allocate() on the Vault", allocate); task("capital", "Set the Vault's pauseCapital flag", capital); task("harvest", "Call harvest() on Vault", harvest); task("rebase", "Call rebase() on the Vault", rebase); -task("yield", "Artificially generate yield on the Vault", yield); +task("yield", "Artificially generate yield on the Vault", yieldTask); // Governance tasks task("execute", "Execute a governance proposal") diff --git a/contracts/tasks/vault.js b/contracts/tasks/vault.js index a59aad2d7f..5309cb4bb5 100644 --- a/contracts/tasks/vault.js +++ b/contracts/tasks/vault.js @@ -1,5 +1,3 @@ -const { utils } = require("ethers"); - const addresses = require("../utils/addresses"); async function allocate(taskArguments, hre) { @@ -73,7 +71,7 @@ async function rebase(taskArguments, hre) { /** * Artificially generate yield on the vault by sending it USDT. */ -async function yield(taskArguments, hre) { +async function yieldTask(taskArguments, hre) { const usdtAbi = require("../test/abi/usdt.json").abi; const { ousdUnitsFormat, @@ -179,5 +177,5 @@ module.exports = { capital, harvest, rebase, - yield, + yieldTask, }; diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 283a527a80..bb7e943ebb 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -3,6 +3,10 @@ const hre = require("hardhat"); const { ethers } = hre; const addresses = require("../utils/addresses"); +const { + balancer_rETH_WETH_PID, + balancer_stETH_WETH_PID, +} = require("../utils/constants"); const { fundAccounts, fundAccountsForOETHUnitTests, @@ -26,6 +30,7 @@ const threepoolSwapAbi = require("./abi/threepoolSwap.json"); const sfrxETHAbi = require("./abi/sfrxETH.json"); const { deployWithConfirmation } = require("../utils/deploy"); const { defaultAbiCoder, parseUnits, parseEther } = require("ethers/lib/utils"); +const balancerStrategyDeployment = require("../utils/balancerStrategyDeployment"); const defaultFixture = deployments.createFixture(async () => { await deployments.fixture( @@ -162,7 +167,7 @@ const defaultFixture = deployments.createFixture(async () => { morpho, morphoCompoundStrategy, fraxEthStrategy, - balancerWstEthWethStrategy, + balancerREthStrategy, morphoAaveStrategy, oethMorphoAaveStrategy, morphoLens, @@ -204,12 +209,10 @@ const defaultFixture = deployments.createFixture(async () => { ausdt = await ethers.getContractAt(erc20Abi, addresses.mainnet.aUSDT); ausdc = await ethers.getContractAt(erc20Abi, addresses.mainnet.aUSDC); adai = await ethers.getContractAt(erc20Abi, addresses.mainnet.aDAI); - reth = await ethers.getContractAt(erc20Abi, addresses.mainnet.rETH); + reth = await ethers.getContractAt("IRETH", addresses.mainnet.rETH); stETH = await ethers.getContractAt(erc20Abi, addresses.mainnet.stETH); frxETH = await ethers.getContractAt(erc20Abi, addresses.mainnet.frxETH); sfrxETH = await ethers.getContractAt(sfrxETHAbi, addresses.mainnet.sfrxETH); - reth = await ethers.getContractAt(erc20Abi, addresses.mainnet.rETH); - stETH = await ethers.getContractAt(erc20Abi, addresses.mainnet.stETH); morpho = await ethers.getContractAt(morphoAbi, addresses.mainnet.Morpho); morphoLens = await ethers.getContractAt( morphoLensAbi, @@ -266,12 +269,12 @@ const defaultFixture = deployments.createFixture(async () => { fraxEthStrategyProxy.address ); - const balancerWstEthWethStrategyProxy = await ethers.getContract( - "OETHBalancerMetaPoolWstEthWethStrategyProxy" + const balancerRethStrategyProxy = await ethers.getContract( + "OETHBalancerMetaPoolrEthStrategyProxy" ); - balancerWstEthWethStrategy = await ethers.getContractAt( + balancerREthStrategy = await ethers.getContractAt( "BalancerMetaPoolStrategy", - balancerWstEthWethStrategyProxy.address + balancerRethStrategyProxy.address ); const oethHarvesterProxy = await ethers.getContract("OETHHarvesterProxy"); @@ -549,7 +552,7 @@ const defaultFixture = deployments.createFixture(async () => { frxETH, sfrxETH, fraxEthStrategy, - balancerWstEthWethStrategy, + balancerREthStrategy, oethMorphoAaveStrategy, woeth, ConvexEthMetaStrategy, @@ -829,26 +832,98 @@ async function convexVaultFixture() { } /** - * Configure a Vault with only the balancerWstEthWethStrategy + * Configure a Vault with the balancerREthStrategy */ -async function balancerWstEthWethFixture() { - const fixture = await loadFixture(defaultFixture); - const { oethVault, timelock, weth, stETH, balancerWstEthWethStrategy } = - fixture; +function balancerREthFixtureSetup() { + return deployments.createFixture(async () => { + const fixture = await defaultFixture(); + const { oethVault, timelock, weth, reth, balancerREthStrategy, josh } = + fixture; - await oethVault - .connect(timelock) - .setAssetDefaultStrategy(weth.address, balancerWstEthWethStrategy.address); - await oethVault - .connect(timelock) - .setAssetDefaultStrategy(stETH.address, balancerWstEthWethStrategy.address); - await oethVault - .connect(timelock) - .setAssetDefaultStrategy(weth.address, balancerWstEthWethStrategy.address); - await oethVault - .connect(timelock) - .setAssetDefaultStrategy(stETH.address, balancerWstEthWethStrategy.address); - return fixture; + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(reth.address, balancerREthStrategy.address); + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(weth.address, balancerREthStrategy.address); + + fixture.rEthBPT = await ethers.getContractAt( + "IERC20Metadata", + addresses.mainnet.rETH_WETH_BPT, + josh + ); + fixture.balancerREthPID = balancer_rETH_WETH_PID; + + fixture.balancerVault = await ethers.getContractAt( + "IBalancerVault", + addresses.mainnet.balancerVault, + josh + ); + + return fixture; + }); +} + +/** + * Configure a Vault with the balancer strategy for wstETH/WETH pool + */ +function balancerWstEthFixtureSetup() { + return deployments.createFixture(async () => { + const fixture = await defaultFixture(); + + const d = balancerStrategyDeployment({ + deploymentOpts: { + deployName: "99999_balancer_wstETH_WETH", + forceDeploy: true, + deployerIsProposer: true, + }, + proxyContractName: "OETHBalancerMetaPoolwstEthStrategyProxy", + + platformAddress: addresses.mainnet.wstETH_WETH_BPT, + poolId: balancer_stETH_WETH_PID, + + auraRewardsContractAddress: addresses.mainnet.wstETH_WETH_AuraRewards, + + rewardTokenAddresses: [addresses.mainnet.BAL, addresses.mainnet.AURA], + assets: [addresses.mainnet.stETH, addresses.mainnet.WETH], + }); + + await d(hre); + + const balancerWstEthStrategyProxy = await ethers.getContract( + "OETHBalancerMetaPoolwstEthStrategyProxy" + ); + const balancerWstEthStrategy = await ethers.getContractAt( + "BalancerMetaPoolStrategy", + balancerWstEthStrategyProxy.address + ); + + fixture.balancerWstEthStrategy = balancerWstEthStrategy; + + const { oethVault, timelock, weth, stETH, josh } = fixture; + + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(stETH.address, balancerWstEthStrategy.address); + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(weth.address, balancerWstEthStrategy.address); + + fixture.stEthBPT = await ethers.getContractAt( + "IERC20Metadata", + addresses.mainnet.wstETH_WETH_BPT, + josh + ); + fixture.balancerWstEthPID = balancer_stETH_WETH_PID; + + fixture.balancerVault = await ethers.getContractAt( + "IBalancerVault", + addresses.mainnet.balancerVault, + josh + ); + + return fixture; + }); } async function fundWith3Crv(address, maxAmount) { @@ -1402,18 +1477,24 @@ async function compoundFixture() { await deploy("StandaloneCompound", { from: governorAddr, contract: "CompoundStrategy", + args: [ + [ + addresses.dead, + governorAddr, // Using Governor in place of Vault here + ], + ], }); fixture.cStandalone = await ethers.getContract("StandaloneCompound"); // Set governor as vault - await fixture.cStandalone.connect(sGovernor).initialize( - addresses.dead, - governorAddr, // Using Governor in place of Vault here - [assetAddresses.COMP], - [assetAddresses.DAI, assetAddresses.USDC], - [assetAddresses.cDAI, assetAddresses.cUSDC] - ); + await fixture.cStandalone + .connect(sGovernor) + .initialize( + [assetAddresses.COMP], + [assetAddresses.DAI, assetAddresses.USDC], + [assetAddresses.cDAI, assetAddresses.cUSDC] + ); await fixture.cStandalone .connect(sGovernor) @@ -1440,6 +1521,12 @@ async function threepoolFixture() { await deploy("StandaloneThreePool", { from: governorAddr, contract: "ThreePoolStrategy", + args: [ + [ + assetAddresses.ThreePool, + governorAddr, // Using Governor in place of Vault here + ], + ], }); fixture.tpStandalone = await ethers.getContract("StandaloneThreePool"); @@ -1447,20 +1534,8 @@ async function threepoolFixture() { // Set governor as vault await fixture.tpStandalone.connect(sGovernor)[ // eslint-disable-next-line - "initialize(address,address,address[],address[],address[],address,address)" - ]( - assetAddresses.ThreePool, - governorAddr, // Using Governor in place of Vault here - [assetAddresses.CRV], - [assetAddresses.DAI, assetAddresses.USDC, assetAddresses.USDT], - [ - assetAddresses.ThreePoolToken, - assetAddresses.ThreePoolToken, - assetAddresses.ThreePoolToken, - ], - assetAddresses.ThreePoolGauge, - assetAddresses.CRVMinter - ); + "initialize(address[],address[],address[],address,address)" + ]([assetAddresses.CRV], [assetAddresses.DAI, assetAddresses.USDC, assetAddresses.USDT], [assetAddresses.ThreePoolToken, assetAddresses.ThreePoolToken, assetAddresses.ThreePoolToken], assetAddresses.ThreePoolGauge, assetAddresses.CRVMinter); return fixture; } @@ -1649,7 +1724,8 @@ module.exports = { impersonateAndFundContract, impersonateAccount, fraxETHStrategyFixtureSetup, - balancerWstEthWethFixture, + balancerREthFixtureSetup, + balancerWstEthFixtureSetup, oethMorphoAaveFixtureSetup, mintWETH, replaceContractAt, diff --git a/contracts/test/helpers.js b/contracts/test/helpers.js index c039f863f1..9cc677c7bc 100644 --- a/contracts/test/helpers.js +++ b/contracts/test/helpers.js @@ -124,7 +124,7 @@ chai.Assertion.addMethod( async function (expected, asset, message) { const strategy = this._obj; const assetAddress = asset.address || asset.getAddress(); - const actual = await strategy.checkBalance(assetAddress); + const actual = await strategy["checkBalance(address)"](assetAddress); if (!BigNumber.isBigNumber(expected)) { expected = parseUnits(expected, await decimalsFor(asset)); } @@ -654,7 +654,7 @@ async function differenceInStrategyBalance( const returnVals = Array(arrayLength); for (let i = 0; i < arrayLength; i++) { - balancesBefore[i] = await strategyContracts[i].checkBalance( + balancesBefore[i] = await strategyContracts[i]["checkBalance(address)"]( assetAddresses[i] ); } @@ -662,7 +662,7 @@ async function differenceInStrategyBalance( for (let i = 0; i < arrayLength; i++) { returnVals[i] = ( - await strategyContracts[i].checkBalance(assetAddresses[i]) + await strategyContracts[i]["checkBalance(address)"](assetAddresses[i]) ).sub(balancesBefore[i]); } diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index ee2679d76d..9418b05938 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -1,15 +1,24 @@ const { expect } = require("chai"); - -const { loadFixture } = require("ethereum-waffle"); -const { units, ousdUnits, forkOnlyDescribe } = require("../helpers"); +const { formatUnits } = require("ethers/lib/utils"); const { BigNumber } = require("ethers"); + +const addresses = require("../../utils/addresses"); +const { balancer_rETH_WETH_PID } = require("../../utils/constants"); +const { units, oethUnits, forkOnlyDescribe } = require("../helpers"); const { - balancerWstEthWethFixture, + balancerREthFixtureSetup, + balancerWstEthFixtureSetup, impersonateAndFundContract, + defaultFixtureSetup, } = require("../_fixture"); +const log = require("../../utils/logger")("test:fork:strategy:balancer"); + +const balancerREthFixture = balancerREthFixtureSetup(); +const balancerWstEthFixture = balancerWstEthFixtureSetup(); + forkOnlyDescribe( - "ForkTest: Balancer MetaStablePool stWeth/WETH Strategy", + "ForkTest: Balancer MetaStablePool rETH/WETH Strategy", function () { this.timeout(0); // due to hardhat forked mode timeouts - retry failed tests up to 3 times @@ -17,25 +26,124 @@ forkOnlyDescribe( let fixture; beforeEach(async () => { - fixture = await loadFixture(balancerWstEthWethFixture); + fixture = await balancerREthFixture(); + }); + + after(async () => { + // This is needed to revert fixtures + // The other tests as of now don't use proper fixtures + // Rel: https://github.com/OriginProtocol/origin-dollar/issues/1259 + const f = defaultFixtureSetup(); + await f(); }); - describe.only("Mint", function () { - it("Should deploy WETH in Balancer MetaStablePool strategy", async function () { - const { josh, weth, stETH } = fixture; - await mintTest(fixture, josh, weth, "30", [weth, stETH]); + describe("Post deployment", () => { + it("Should have the correct initial state", async function () { + const { balancerREthStrategy, oethVault } = fixture; + + // Platform and OToken Vault + expect(await balancerREthStrategy.platformAddress()).to.equal( + addresses.mainnet.rETH_WETH_BPT + ); + expect(await balancerREthStrategy.vaultAddress()).to.equal( + oethVault.address + ); + + // Balancer and Aura config + expect(await balancerREthStrategy.balancerVault()).to.equal( + addresses.mainnet.balancerVault + ); + expect(await balancerREthStrategy.balancerPoolId()).to.equal( + balancer_rETH_WETH_PID + ); + expect(await balancerREthStrategy.auraRewardPoolAddress()).to.equal( + addresses.mainnet.rETH_WETH_AuraRewards + ); + + // Check slippage values + expect(await balancerREthStrategy.maxDepositSlippage()).to.equal( + oethUnits("0.001") + ); + expect(await balancerREthStrategy.maxWithdrawalSlippage()).to.equal( + oethUnits("0.001") + ); + // Check addresses + expect(await balancerREthStrategy.rETH()).to.equal( + addresses.mainnet.rETH + ); + expect(await balancerREthStrategy.wstETH()).to.equal( + addresses.mainnet.wstETH + ); + expect(await balancerREthStrategy.stETH()).to.equal( + addresses.mainnet.stETH + ); + expect(await balancerREthStrategy.sfrxETH()).to.equal( + addresses.mainnet.sfrxETH + ); + expect(await balancerREthStrategy.frxETH()).to.equal( + addresses.mainnet.frxETH + ); }); + }); - it("Should deploy stETH in Balancer MetaStablePool strategy", async function () { - const { josh, stETH, weth } = fixture; - await mintTest(fixture, josh, stETH, "30", [weth, stETH]); + describe("Deposit", function () { + beforeEach(async () => { + const { timelock, reth, weth, oethVault } = fixture; + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(reth.address, addresses.zero); + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(weth.address, addresses.zero); + }); + it("Should deposit 5 WETH and 5 rETH in Balancer MetaStablePool strategy", async function () { + const { reth, rEthBPT, weth } = fixture; + await depositTest(fixture, [5, 5], [weth, reth], rEthBPT); }); + it("Should deposit 12 WETH in Balancer MetaStablePool strategy", async function () { + const { reth, rEthBPT, weth } = fixture; + await depositTest(fixture, [12, 0], [weth, reth], rEthBPT); + }); + it("Should deposit 30 rETH in Balancer MetaStablePool strategy", async function () { + const { reth, rEthBPT, weth } = fixture; + await depositTest(fixture, [0, 30], [weth, reth], rEthBPT); + }); + it("Should deposit all WETH and rETH in strategy to pool", async function () { + const { balancerREthStrategy, oethVault, reth, weth } = fixture; + + const rethInVaultBefore = await reth.balanceOf(oethVault.address); + const wethInVaultBefore = await weth.balanceOf(oethVault.address); + const strategyValueBefore = await balancerREthStrategy[ + "checkBalance()" + ](); - it("Should have the correct initial maxDepositSlippage state", async function () { - const { balancerWstEthWethStrategy, josh } = fixture; + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + const rethUnits = oethUnits("7"); + const rethValue = await reth.getEthValue(rethUnits); + await reth + .connect(oethVaultSigner) + .transfer(balancerREthStrategy.address, rethUnits); + const wethUnits = oethUnits("8"); + await weth + .connect(oethVaultSigner) + .transfer(balancerREthStrategy.address, wethUnits); + + await balancerREthStrategy.connect(oethVaultSigner).depositAll(); + + const rethInVaultAfter = await reth.balanceOf(oethVault.address); + const wethInVaultAfter = await weth.balanceOf(oethVault.address); + const strategyValueAfter = await balancerREthStrategy[ + "checkBalance()" + ](); + + expect(rethInVaultBefore.sub(rethInVaultAfter)).to.equal(rethUnits); + expect(wethInVaultBefore.sub(wethInVaultAfter)).to.equal(wethUnits); expect( - await balancerWstEthWethStrategy.connect(josh).maxDepositSlippage() - ).to.equal(ousdUnits("0.001")); + strategyValueAfter.sub(strategyValueBefore) + ).to.approxEqualTolerance(rethValue.add(wethUnits), 0.01); }); it("Should be able to deposit with higher deposit slippage", async function () {}); @@ -49,134 +157,528 @@ forkOnlyDescribe( * - transaction should revert because of the `whenNotInVaultContext` modifier */ }); + + it("Should check balance for gas usage", async () => { + const { balancerREthStrategy, josh, weth } = fixture; + + // Check balance in a transaction so the gas usage can be measured + await balancerREthStrategy["checkBalance(address)"](weth.address); + const tx = await balancerREthStrategy + .connect(josh) + .populateTransaction["checkBalance(address)"](weth.address); + await josh.sendTransaction(tx); + }); }); - describe.only("Withdraw", function () { - it("Should be able to withdraw some amount of pool liquidity", async function () { - const { josh, weth, stETH, balancerWstEthWethStrategy, oethVault } = + describe("Withdraw", function () { + beforeEach(async () => { + const { balancerREthStrategy, oethVault, strategist, reth, weth } = fixture; - await mintTest(fixture, josh, weth, "30", [weth, stETH]); - const wethBalanceBeforeVault = await weth.balanceOf(oethVault.address); - const wethToWithdraw = await units("10", weth); + await oethVault + .connect(strategist) + .depositToStrategy( + balancerREthStrategy.address, + [weth.address, reth.address], + [oethUnits("22"), oethUnits("25")] + ); + }); + it("Should be able to withdraw 10 WETH from the pool", async function () { + const { weth, balancerREthStrategy, oethVault } = fixture; + + const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); + const withdrawAmount = await units("10", weth); const oethVaultSigner = await impersonateAndFundContract( oethVault.address ); - await balancerWstEthWethStrategy - .connect(oethVaultSigner) - .withdraw(oethVault.address, weth.address, wethToWithdraw); + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( + oethVault.address, + weth.address, + withdrawAmount + ); + + const vaultWethBalanceAfter = await weth.balanceOf(oethVault.address); + const wethBalanceDiffVault = vaultWethBalanceAfter.sub( + vaultWethBalanceBefore + ); + expect(wethBalanceDiffVault).to.approxEqualTolerance( + withdrawAmount, + 0.01 + ); + }); + it("Should be able to withdraw 8 RETH from the pool", async function () { + const { reth, balancerREthStrategy, oethVault } = fixture; - const wethBalanceDiffVault = ( - await weth.balanceOf(oethVault.address) - ).sub(wethBalanceBeforeVault); - expect(wethBalanceDiffVault).to.approxEqualTolerance(wethToWithdraw, 1); + const vaultRethBalanceBefore = await reth.balanceOf(oethVault.address); + const withdrawAmount = await units("8", reth); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( + oethVault.address, + reth.address, + withdrawAmount + ); + + const vaultRethBalanceAfter = await reth.balanceOf(oethVault.address); + const rethBalanceDiffVault = vaultRethBalanceAfter.sub( + vaultRethBalanceBefore + ); + expect(rethBalanceDiffVault).to.approxEqualTolerance( + withdrawAmount, + 0.01 + ); }); + it("Should be able to withdraw 11 WETH and 14 RETH from the pool", async function () { + const { reth, balancerREthStrategy, oethVault, weth } = fixture; - it("Should be able to withdraw all of pool liquidity", async function () { - const { josh, weth, stETH, balancerWstEthWethStrategy, oethVault } = - fixture; - await mintTest(fixture, josh, weth, "30", [weth, stETH]); + const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); + const vaultRethBalanceBefore = await reth.balanceOf(oethVault.address); + const wethWithdrawAmount = await units("11", weth); + const rethWithdrawAmount = await units("14", reth); - const wethBalanceBefore = await balancerWstEthWethStrategy.checkBalance( - weth.address + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address ); - const stEthBalanceBefore = - await balancerWstEthWethStrategy.checkBalance(stETH.address); + + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( + oethVault.address, + [weth.address, reth.address], + [wethWithdrawAmount, rethWithdrawAmount] + ); + + expect( + (await weth.balanceOf(oethVault.address)).sub(vaultWethBalanceBefore) + ).to.approxEqualTolerance(wethWithdrawAmount, 0.01); + expect( + (await reth.balanceOf(oethVault.address)).sub(vaultRethBalanceBefore) + ).to.approxEqualTolerance(rethWithdrawAmount, 0.01); + }); + + it("Should be able to withdraw all of pool liquidity", async function () { + const { oethVault, weth, reth, balancerREthStrategy } = fixture; + + const wethBalanceBefore = await balancerREthStrategy[ + "checkBalance(address)" + ](weth.address); + const stEthBalanceBefore = await balancerREthStrategy[ + "checkBalance(address)" + ](reth.address); const oethVaultSigner = await impersonateAndFundContract( oethVault.address ); - await balancerWstEthWethStrategy.connect(oethVaultSigner).withdrawAll(); + await balancerREthStrategy.connect(oethVaultSigner).withdrawAll(); const wethBalanceDiff = wethBalanceBefore.sub( - await balancerWstEthWethStrategy.checkBalance(weth.address) + await balancerREthStrategy["checkBalance(address)"](weth.address) ); const stEthBalanceDiff = stEthBalanceBefore.sub( - await balancerWstEthWethStrategy.checkBalance(stETH.address) + await balancerREthStrategy["checkBalance(address)"](reth.address) ); expect(wethBalanceDiff).to.be.gte(await units("15", weth), 1); - expect(stEthBalanceDiff).to.be.gte(await units("15", stETH), 1); + expect(stEthBalanceDiff).to.be.gte(await units("15", reth), 1); + }); + + it("Should be able to withdraw with higher withdrawal slippage", async function () {}); + }); + + describe("Harvest rewards", function () { + it("Should be able to collect reward tokens", async function () { + const { josh, balancerREthStrategy, oethHarvester } = fixture; + + await oethHarvester.connect(josh)[ + // eslint-disable-next-line + "harvestAndSwap(address)" + ](balancerREthStrategy.address); }); + }); + } +); - it("Should have the correct initial maxWithdrawalSlippage state", async function () { - const { balancerWstEthWethStrategy, josh } = fixture; +forkOnlyDescribe( + "ForkTest: Balancer MetaStablePool wstETH/WETH Strategy", + function () { + let fixture; + beforeEach(async () => { + fixture = await balancerWstEthFixture(); + }); + + after(async () => { + // This is needed to revert fixtures + // The other tests as of now don't use proper fixtures + // Rel: https://github.com/OriginProtocol/origin-dollar/issues/1259 + const f = defaultFixtureSetup(); + await f(); + }); + + describe("Deposit", function () { + beforeEach(async () => { + const { timelock, stETH, weth, oethVault } = fixture; + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(stETH.address, addresses.zero); + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(weth.address, addresses.zero); + }); + + it("Should deposit 5 WETH and 5 stETH in Balancer MetaStablePool strategy", async function () { + const { stETH, stEthBPT, weth } = fixture; + await wstETHDepositTest(fixture, [5, 5], [weth, stETH], stEthBPT); + }); + it("Should deposit 12 WETH in Balancer MetaStablePool strategy", async function () { + const { stETH, stEthBPT, weth } = fixture; + await wstETHDepositTest(fixture, [12, 0], [weth, stETH], stEthBPT); + }); + + it("Should deposit 30 stETH in Balancer MetaStablePool strategy", async function () { + const { stETH, stEthBPT, weth } = fixture; + await wstETHDepositTest(fixture, [0, 30], [weth, stETH], stEthBPT); + }); + + it("Should check balance for gas usage", async () => { + const { balancerWstEthStrategy, josh, weth } = fixture; + + // Check balance in a transaction so the gas usage can be measured + await balancerWstEthStrategy["checkBalance(address)"](weth.address); + const tx = await balancerWstEthStrategy + .connect(josh) + .populateTransaction["checkBalance(address)"](weth.address); + await josh.sendTransaction(tx); + }); + }); + + describe("Withdraw", function () { + beforeEach(async () => { + const { balancerWstEthStrategy, oethVault, strategist, stETH, weth } = + fixture; + + await oethVault + .connect(strategist) + .depositToStrategy( + balancerWstEthStrategy.address, + [weth.address, stETH.address], + [oethUnits("25"), oethUnits("25")] + ); + + // TODO: Check slippage errors + await balancerWstEthStrategy + .connect(strategist) + .setMaxWithdrawalSlippage(oethUnits("0.01")); + }); + it("Should be able to withdraw 10 WETH from the pool", async function () { + const { weth, balancerWstEthStrategy, oethVault } = fixture; + + const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); + const withdrawAmount = await units("10", weth); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + // prettier-ignore + await balancerWstEthStrategy + .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( + oethVault.address, + weth.address, + withdrawAmount + ); + + const vaultWethBalanceAfter = await weth.balanceOf(oethVault.address); + const wethBalanceDiffVault = vaultWethBalanceAfter.sub( + vaultWethBalanceBefore + ); + expect(wethBalanceDiffVault).to.approxEqualTolerance(withdrawAmount, 1); + }); + it("Should be able to withdraw 8 stETH from the pool", async function () { + const { stETH, balancerWstEthStrategy, oethVault } = fixture; + + const vaultstETHBalanceBefore = await stETH.balanceOf( + oethVault.address + ); + const withdrawAmount = await units("8", stETH); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + // prettier-ignore + await balancerWstEthStrategy + .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( + oethVault.address, + stETH.address, + withdrawAmount + ); + + const vaultstETHBalanceAfter = await stETH.balanceOf(oethVault.address); + const stETHBalanceDiffVault = vaultstETHBalanceAfter.sub( + vaultstETHBalanceBefore + ); + expect(stETHBalanceDiffVault).to.approxEqualTolerance( + withdrawAmount, + 1 + ); + }); + it("Should be able to withdraw 11 WETH and 14 stETH from the pool", async function () { + const { stETH, balancerWstEthStrategy, oethVault, weth } = fixture; + + const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); + const vaultstEthBalanceBefore = await stETH.balanceOf( + oethVault.address + ); + const wethWithdrawAmount = await units("11", weth); + const stETHWithdrawAmount = await units("14", stETH); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + // prettier-ignore + await balancerWstEthStrategy + .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( + oethVault.address, + [weth.address, stETH.address], + [wethWithdrawAmount, stETHWithdrawAmount] + ); + + expect( + (await weth.balanceOf(oethVault.address)).sub(vaultWethBalanceBefore) + ).to.approxEqualTolerance(wethWithdrawAmount, 1); expect( - await balancerWstEthWethStrategy.connect(josh).maxWithdrawalSlippage() - ).to.equal(ousdUnits("0.001")); + (await stETH.balanceOf(oethVault.address)).sub( + vaultstEthBalanceBefore + ) + ).to.approxEqualTolerance(stETHWithdrawAmount, 1); }); - it("Should be able to withdraw with higher withdrawal slippage", async function () {}); + it("Should be able to withdraw all of pool liquidity", async function () { + const { oethVault, weth, stETH, balancerWstEthStrategy } = fixture; + + const wethBalanceBefore = await balancerWstEthStrategy[ + "checkBalance(address)" + ](weth.address); + const stEthBalanceBefore = await balancerWstEthStrategy[ + "checkBalance(address)" + ](stETH.address); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + await balancerWstEthStrategy.connect(oethVaultSigner).withdrawAll(); + + const wethBalanceDiff = wethBalanceBefore.sub( + await balancerWstEthStrategy["checkBalance(address)"](weth.address) + ); + const stEthBalanceDiff = stEthBalanceBefore.sub( + await balancerWstEthStrategy["checkBalance(address)"](stETH.address) + ); + + expect(wethBalanceDiff).to.be.gte(await units("15", weth), 1); + expect(stEthBalanceDiff).to.be.gte(await units("15", stETH), 1); + }); }); - describe.only("Harvest rewards", function () { + describe("Harvest rewards", function () { it("Should be able to collect reward tokens", async function () { - const { josh, balancerWstEthWethStrategy, oethHarvester } = fixture; + const { josh, balancerWstEthStrategy, oethHarvester } = fixture; await oethHarvester.connect(josh)[ // eslint-disable-next-line "harvestAndSwap(address)" - ](balancerWstEthWethStrategy.address); + ](balancerWstEthStrategy.address); }); }); } ); -async function getPoolBalance(strategy, allAssets) { - let currentBalancerBalance = BigNumber.from(0); +async function getPoolValues(strategy, allAssets, reth) { + const result = { + sum: BigNumber.from(0), + }; for (const asset of allAssets) { - currentBalancerBalance = currentBalancerBalance.add( - await strategy.checkBalance(asset.address) + const assetSymbol = await asset.symbol(); + const strategyAssetBalance = await strategy["checkBalance(address)"]( + asset.address + ); + log( + `Balancer ${assetSymbol} balance: ${formatUnits(strategyAssetBalance)}` ); + const strategyAssetValue = + asset.address === reth.address + ? await reth.getEthValue(strategyAssetBalance) + : strategyAssetBalance; + result.sum = result.sum.add(strategyAssetValue); + log(`Balancer ${assetSymbol} value: ${formatUnits(strategyAssetValue)}`); + result[assetSymbol] = strategyAssetBalance; } + log(`Balancer sum values: ${formatUnits(result.sum)}`); + + result.value = await strategy["checkBalance()"](); + log(`Balancer value: ${formatUnits(result.value)}`); + + return result; +} - return currentBalancerBalance; +async function getPoolBalances(balancerVault, pid) { + const result = {}; + const { tokens, balances } = await balancerVault.getPoolTokens(pid); + let i = 0; + for (const balance of balances) { + const assetAddr = tokens[i++]; + log(`${assetAddr} pool balance: ${formatUnits(balance)}`); + result[assetAddr] = balance; + } + return result; } -async function mintTest(fixture, user, asset, amount, allAssets) { - const { oethVault, oeth, balancerWstEthWethStrategy } = fixture; +async function depositTest(fixture, amounts, allAssets, bpt) { + const { + oethVault, + oeth, + balancerREthStrategy, + balancerVault, + balancerREthPID, + reth, + strategist, + } = fixture; + const logParams = { + oeth, + oethVault, + bpt, + balancerVault, + strategy: balancerREthStrategy, + allAssets, + pid: balancerREthPID, + reth, + }; + + const unitAmounts = amounts.map((amount) => oethUnits(amount.toString())); + const ethAmounts = await Promise.all( + allAssets.map((asset, i) => + asset.address === reth.address + ? reth.getEthValue(unitAmounts[i]) + : unitAmounts[i] + ) + ); + const sumEthAmounts = ethAmounts.reduce( + (a, b) => a.add(b), + BigNumber.from(0) + ); - await oethVault.connect(user).allocate(); - const unitAmount = await units(amount, asset); + const before = await logBalances(logParams); - const currentSupply = await oeth.totalSupply(); - const currentBalance = await oeth.connect(user).balanceOf(user.address); - const currentBalancerBalance = await getPoolBalance( - balancerWstEthWethStrategy, - allAssets + await oethVault.connect(strategist).depositToStrategy( + balancerREthStrategy.address, + allAssets.map((asset) => asset.address), + unitAmounts ); - // Mint OETH w/ asset - await asset.connect(user).approve(oethVault.address, unitAmount); - await oethVault.connect(user).mint(asset.address, unitAmount, 0); - await oethVault.connect(user).allocate(); + const after = await logBalances(logParams); - const newBalance = await oeth.connect(user).balanceOf(user.address); - const newSupply = await oeth.totalSupply(); - const newBalancerBalance = await getPoolBalance( - balancerWstEthWethStrategy, - allAssets + // Should have liquidity in Balancer + const strategyValuesDiff = after.strategyValues.sum.sub( + before.strategyValues.sum ); + expect(strategyValuesDiff).to.approxEqualTolerance(sumEthAmounts, 0.1); + expect( + after.strategyValues.value, + "strategy total value = sum of asset values" + ).to.approxEqualTolerance(after.strategyValues.sum, 0.01); +} - const balanceDiff = newBalance.sub(currentBalance); - // Ensure user has correct balance (w/ 1% slippage tolerance) - expect(balanceDiff).to.approxEqualTolerance(ousdUnits(amount), 1); +async function wstETHDepositTest(fixture, amounts, allAssets, bpt) { + const { + oethVault, + oeth, + balancerWstEthStrategy, + balancerVault, + balancerWstEthPID, + strategist, + reth, + } = fixture; + const logParams = { + oeth, + oethVault, + bpt, + balancerVault, + strategy: balancerWstEthStrategy, + allAssets, + pid: balancerWstEthPID, + reth, + }; + + const unitAmounts = amounts.map((amount) => oethUnits(amount.toString())); + const ethAmounts = unitAmounts; + const sumEthAmounts = ethAmounts.reduce( + (a, b) => a.add(b), + BigNumber.from(0) + ); - // Supply checks - const supplyDiff = newSupply.sub(currentSupply); - const ousdUnitAmount = ousdUnits(amount); + const before = await logBalances(logParams); - expect(supplyDiff).to.approxEqualTolerance(ousdUnitAmount, 1); + await oethVault.connect(strategist).depositToStrategy( + balancerWstEthStrategy.address, + allAssets.map((asset) => asset.address), + unitAmounts + ); - const balancerLiquidityDiff = newBalancerBalance.sub(currentBalancerBalance); + const after = await logBalances(logParams); // Should have liquidity in Balancer - expect(balancerLiquidityDiff).to.approxEqualTolerance( - await units(amount, asset), - 1 + const strategyValuesDiff = after.strategyValues.sum.sub( + before.strategyValues.sum ); + expect(strategyValuesDiff).to.approxEqualTolerance(sumEthAmounts, 1); + expect( + after.strategyValues.value, + "strategy total value = sum of asset values" + ).to.approxEqualTolerance(after.strategyValues.sum, 1); +} + +async function logBalances({ + oeth, + oethVault, + bpt, + balancerVault, + pid, + strategy, + allAssets, + reth, +}) { + const oethSupply = await oeth.totalSupply(); + const bptSupply = await bpt.totalSupply(); + + log(`\nOETH total supply: ${formatUnits(oethSupply)}`); + log(`BPT total supply : ${formatUnits(bptSupply)}`); + + for (const asset of allAssets) { + const vaultAssets = await asset.balanceOf(oethVault.address); + log(`${await asset.symbol()} in vault ${formatUnits(vaultAssets)}`); + } + + const strategyValues = await getPoolValues(strategy, allAssets, reth); + + const poolBalances = await getPoolBalances(balancerVault, pid); + + return { + oethSupply, + bptSupply, + strategyValues, + poolBalances, + }; } diff --git a/contracts/utils/addresses.js b/contracts/utils/addresses.js index 02c333fd0b..22e996fb56 100644 --- a/contracts/utils/addresses.js +++ b/contracts/utils/addresses.js @@ -153,6 +153,7 @@ addresses.mainnet.CompensationClaims = "0x9C94df9d594BA1eb94430C006c269C314B1A8281"; addresses.mainnet.Flipper = "0xcecaD69d7D4Ed6D52eFcFA028aF8732F27e08F70"; +// Morpho addresses.mainnet.Morpho = "0x8888882f8f843896699869179fB6E4f7e3B58888"; addresses.mainnet.MorphoLens = "0x930f1b46e1d081ec1524efd95752be3ece51ef67"; @@ -168,22 +169,38 @@ addresses.mainnet.OETHVaultProxy = "0x39254033945aa2e4809cc2977e7087bee48bd7ab"; addresses.mainnet.OETHZapper = "0x9858e47BCbBe6fBAC040519B02d7cd4B2C470C66"; addresses.mainnet.FraxETHStrategy = "0x3ff8654d633d4ea0fae24c52aec73b4a20d0d0e5"; -addresses.mainnet.BAL = "0xba100000625a3754423978a60c9317c58a424e3D"; -addresses.mainnet.AURA = "0xc0c293ce456ff0ed870add98a0828dd4d2903dbf"; -addresses.mainnet.wstETH = "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0"; -addresses.mainnet.wstETH_WETH_BPT = - "0x32296969ef14eb0c6d29669c550d4a0449130230"; -addresses.mainnet.auraRewardPool = "0x59d66c58e83a26d6a0e35114323f65c3945c89c1"; -// Tokens +// OETH Tokens addresses.mainnet.sfrxETH = "0xac3E018457B222d93114458476f3E3416Abbe38F"; addresses.mainnet.frxETH = "0x5E8422345238F34275888049021821E8E08CAa1f"; addresses.mainnet.rETH = "0xae78736Cd615f374D3085123A210448E74Fc6393"; addresses.mainnet.stETH = "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"; +addresses.mainnet.wstETH = "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"; addresses.mainnet.FraxETHMinter = "0xbAFA44EFE7901E04E39Dad13167D089C559c1138"; // 1Inch addresses.mainnet.oneInchRouterV5 = "0x1111111254EEB25477B68fb85Ed929f73A960582"; +// Balancer +addresses.mainnet.BAL = "0xba100000625a3754423978a60c9317c58a424e3D"; +addresses.mainnet.balancerVault = "0xBA12222222228d8Ba445958a75a0704d566BF2C8"; +// wstETH/WETH +addresses.mainnet.wstETH_WETH_BPT = + "0x32296969Ef14EB0c6d29669C550D4a0449130230"; +addresses.mainnet.wstETH_WETH_AuraRewards = + "0x59D66C58E83A26d6a0E35114323f65c3945c89c1"; +// rETH/WETH +addresses.mainnet.rETH_WETH_BPT = "0x1E19CF2D73a72Ef1332C882F20534B6519Be0276"; +addresses.mainnet.rETH_WETH_AuraRewards = + "0xDd1fE5AD401D4777cE89959b7fa587e569Bf125D"; +// wstETH/sfrxETH/rETH +addresses.mainnet.wstETH_sfrxETH_rETH_BPT = + "0x42ed016f826165c2e5976fe5bc3df540c5ad0af7"; +addresses.mainnet.wstETH_sfrxETH_rETH_AuraRewards = + "0xd26948E7a0223700e3C3cdEA21cA2471abCb8d47"; + +// Aura +addresses.mainnet.AURA = "0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF"; + module.exports = addresses; diff --git a/contracts/utils/balancerStrategyDeployment.js b/contracts/utils/balancerStrategyDeployment.js new file mode 100644 index 0000000000..14b856b141 --- /dev/null +++ b/contracts/utils/balancerStrategyDeployment.js @@ -0,0 +1,125 @@ +const { deploymentWithGovernanceProposal } = require("./deploy"); +const addresses = require("../utils/addresses"); + +module.exports = ({ + deploymentOpts, + + proxyContractName, + + platformAddress, // Address of the Balancer pool + poolId, // Pool ID of the Balancer pool + + auraRewardsContractAddress, + + rewardTokenAddresses, + assets, +}) => { + return deploymentWithGovernanceProposal( + deploymentOpts, + async ({ deployWithConfirmation, ethers, getTxOpts, withConfirmation }) => { + const { deployerAddr } = await getNamedAccounts(); + const sDeployer = await ethers.provider.getSigner(deployerAddr); + + // Current contracts + const cOETHVaultProxy = await ethers.getContract("OETHVaultProxy"); + const cOETHVaultAdmin = await ethers.getContractAt( + "OETHVaultAdmin", + cOETHVaultProxy.address + ); + + // Deployer Actions + // ---------------- + + // 1. Deploy new proxy + // New strategy will be living at a clean address + const dOETHBalancerMetaPoolStrategyProxy = await deployWithConfirmation( + proxyContractName + ); + const cOETHBalancerMetaPoolStrategyProxy = await ethers.getContractAt( + proxyContractName, + dOETHBalancerMetaPoolStrategyProxy.address + ); + + // 2. Deploy new implementation + const dOETHBalancerMetaPoolStrategyImpl = await deployWithConfirmation( + "BalancerMetaPoolStrategy", + [ + [platformAddress, cOETHVaultProxy.address], + [ + addresses.mainnet.rETH, + addresses.mainnet.stETH, + addresses.mainnet.wstETH, + addresses.mainnet.frxETH, + addresses.mainnet.sfrxETH, + addresses.mainnet.balancerVault, // Address of the Balancer vault + poolId, // Pool ID of the Balancer pool + ], + auraRewardsContractAddress, + ] + ); + const cOETHBalancerMetaPoolStrategy = await ethers.getContractAt( + "BalancerMetaPoolStrategy", + dOETHBalancerMetaPoolStrategyProxy.address + ); + + const cOETHHarvesterProxy = await ethers.getContract( + "OETHHarvesterProxy" + ); + const cOETHHarvester = await ethers.getContractAt( + "OETHHarvester", + cOETHHarvesterProxy.address + ); + + // 3. Encode the init data + const initFunction = "initialize(address[],address[],address[])"; + const initData = + cOETHBalancerMetaPoolStrategy.interface.encodeFunctionData( + initFunction, + [rewardTokenAddresses, assets, [platformAddress, platformAddress]] + ); + + // 4. Init the proxy to point at the implementation + // prettier-ignore + await withConfirmation( + cOETHBalancerMetaPoolStrategyProxy + .connect(sDeployer)["initialize(address,address,bytes)"]( + dOETHBalancerMetaPoolStrategyImpl.address, + addresses.mainnet.Timelock, + initData, + await getTxOpts() + ) + ); + + console.log( + "Balancer strategy address:", + dOETHBalancerMetaPoolStrategyProxy.address + ); + + // Governance Actions + // ---------------- + return { + name: "Deploy new Balancer MetaPool strategy", + actions: [ + // 1. Add new strategy to the vault + { + contract: cOETHVaultAdmin, + signature: "approveStrategy(address)", + args: [cOETHBalancerMetaPoolStrategy.address], + }, + // 2. Set supported strategy on Harvester + { + contract: cOETHHarvester, + signature: "setSupportedStrategy(address,bool)", + args: [cOETHBalancerMetaPoolStrategy.address, true], + }, + // 3. Set harvester address + { + contract: cOETHBalancerMetaPoolStrategy, + signature: "setHarvesterAddress(address)", + args: [cOETHHarvesterProxy.address], + }, + ], + }; + } + ); +}; diff --git a/contracts/utils/constants.js b/contracts/utils/constants.js index ec63f046f9..801d427917 100644 --- a/contracts/utils/constants.js +++ b/contracts/utils/constants.js @@ -1,12 +1,27 @@ -const threeCRVPid = 9; -const metapoolLPCRVPid = 56; -const lusdMetapoolLPCRVPid = 33; -const oethPoolLpPID = 174; -const balancerWstEthWethPID = 115; const { BigNumber } = require("ethers"); + const MAX_UINT256 = BigNumber.from( "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); +const threeCRVPid = 9; +const metapoolLPCRVPid = 56; +const lusdMetapoolLPCRVPid = 33; +const oethPoolLpPID = 174; + +// stETH/WETH +const aura_stETH_WETH_PID = 115; +const balancer_stETH_WETH_PID = + "0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080"; + +// wstETH/sfrcETH/rETH +const aura_wstETH_sfrxETH_rETH_PID = 50; +const balancer_wstETH_sfrxETH_rETH_PID = + "0x42ed016f826165c2e5976fe5bc3df540c5ad0af700000000000000000000058b"; + +// rETH/WETH +const aura_rETH_WETH_PID = 109; +const balancer_rETH_WETH_PID = + "0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112"; module.exports = { threeCRVPid, @@ -14,7 +29,12 @@ module.exports = { lusdMetapoolLPCRVPid, oethPoolLpPID, MAX_UINT256, - balancerWstEthWethPID, + aura_stETH_WETH_PID, + balancer_stETH_WETH_PID, + aura_wstETH_sfrxETH_rETH_PID, + balancer_wstETH_sfrxETH_rETH_PID, + aura_rETH_WETH_PID, + balancer_rETH_WETH_PID, }; // These are all the metapool ids. For easier future reference From 012a83daed75994d4278817b7cd6775324b500df Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 2 Aug 2023 23:34:35 +0200 Subject: [PATCH 21/67] [ DFD-1 ] Balancer's checkBalance (#1730) * add alternative implementation of Balancer's checkBalance * correct the checkBalance implementation --- brownie/abi/balancerUserData.json | 25 +++ brownie/abi/balancer_strat.json | 1 + brownie/balancer_check_balance_test.py | 161 ++++++++++++++++++ ...py => balancer_deposit_withdrawal_test.py} | 0 .../balancer/BalancerMetaPoolStrategy.sol | 36 ++++ .../balancer/BaseBalancerStrategy.sol | 66 +++++-- 6 files changed, 271 insertions(+), 18 deletions(-) create mode 100644 brownie/abi/balancer_strat.json create mode 100644 brownie/balancer_check_balance_test.py rename brownie/{playingAround.py => balancer_deposit_withdrawal_test.py} (100%) diff --git a/brownie/abi/balancerUserData.json b/brownie/abi/balancerUserData.json index 22844d282c..b05b5894f4 100644 --- a/brownie/abi/balancerUserData.json +++ b/brownie/abi/balancerUserData.json @@ -23,5 +23,30 @@ "payable": false, "stateMutability": "nonpayable", "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "joinKind", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "minBptAmountout", + "type": "uint256" + } + ], + "name": "userDataExactTokenInForBPTOut", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/brownie/abi/balancer_strat.json b/brownie/abi/balancer_strat.json new file mode 100644 index 0000000000..28e89124b0 --- /dev/null +++ b/brownie/abi/balancer_strat.json @@ -0,0 +1 @@ +[{"inputs": [{"components": [{"internalType": "address","name": "platformAddress","type": "address"},{"internalType": "address","name": "vaultAddress","type": "address"}],"internalType": "struct InitializableAbstractStrategy.BaseStrategyConfig","name": "_stratConfig","type": "tuple"},{"components": [{"internalType": "address","name": "rEthAddress","type": "address"},{"internalType": "address","name": "stEthAddress","type": "address"},{"internalType": "address","name": "wstEthAddress","type": "address"},{"internalType": "address","name": "frxEthAddress","type": "address"},{"internalType": "address","name": "sfrxEthAddress","type": "address"},{"internalType": "address","name": "balancerVaultAddress","type": "address"},{"internalType": "bytes32","name": "balancerPoolId","type": "bytes32"}],"internalType": "struct BaseBalancerStrategy.BaseBalancerConfig","name": "_balancerConfig","type": "tuple"},{"internalType": "address","name": "_auraRewardPoolAddress","type": "address"}],"stateMutability": "nonpayable","type": "constructor"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "Deposit","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "previousGovernor","type": "address"},{"indexed": true,"internalType": "address","name": "newGovernor","type": "address"}],"name": "GovernorshipTransferred","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address","name": "_oldHarvesterAddress","type": "address"},{"indexed": false,"internalType": "address","name": "_newHarvesterAddress","type": "address"}],"name": "HarvesterAddressesUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "_prevMaxSlippagePercentage","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "_newMaxSlippagePercentage","type": "uint256"}],"name": "MaxDepositSlippageUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "_prevMaxSlippagePercentage","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "_newMaxSlippagePercentage","type": "uint256"}],"name": "MaxWithdrawalSlippageUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"}],"name": "PTokenAdded","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"}],"name": "PTokenRemoved","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "previousGovernor","type": "address"},{"indexed": true,"internalType": "address","name": "newGovernor","type": "address"}],"name": "PendingGovernorshipTransfer","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address[]","name": "_oldAddresses","type": "address[]"},{"indexed": false,"internalType": "address[]","name": "_newAddresses","type": "address[]"}],"name": "RewardTokenAddressesUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address","name": "recipient","type": "address"},{"indexed": false,"internalType": "address","name": "rewardToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "RewardTokenCollected","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "Withdrawal","type": "event"},{"inputs": [{"internalType": "address","name": "","type": "address"}],"name": "assetToPToken","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "auraRewardPoolAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "balancerPoolId","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "balancerVault","outputs": [{"internalType": "contract IBalancerVault","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance2","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance3","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "checkBalance","outputs": [{"internalType": "uint256","name": "value","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "claimGovernance","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "collectRewardTokens","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "deposit","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "uint256[]","name": "_amounts","type": "uint256[]"}],"name": "deposit","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "depositAll","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "frxETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "getRewardTokenAddresses","outputs": [{"internalType": "address[]","name": "","type": "address[]"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "governor","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "harvesterAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address[]","name": "_rewardTokenAddresses","type": "address[]"},{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "address[]","name": "_pTokens","type": "address[]"}],"name": "initialize","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "isGovernor","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxDepositSlippage","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxWithdrawalSlippage","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "platformAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "rETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "_assetIndex","type": "uint256"}],"name": "removePToken","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "","type": "uint256"}],"name": "rewardTokenAddresses","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "safeApproveAllTokens","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_harvesterAddress","type": "address"}],"name": "setHarvesterAddress","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "_maxDepositSlippage","type": "uint256"}],"name": "setMaxDepositSlippage","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "_maxWithdrawalSlippage","type": "uint256"}],"name": "setMaxWithdrawalSlippage","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "address","name": "_pToken","type": "address"}],"name": "setPTokenAddress","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address[]","name": "_rewardTokenAddresses","type": "address[]"}],"name": "setRewardTokenAddresses","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "sfrxETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "stETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "supportsAsset","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_newGovernor","type": "address"}],"name": "transferGovernance","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "transferToken","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "vaultAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_recipient","type": "address"},{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "withdraw","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_recipient","type": "address"},{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "uint256[]","name": "_amounts","type": "uint256[]"}],"name": "withdraw","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "withdrawAll","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "wstETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"}] \ No newline at end of file diff --git a/brownie/balancer_check_balance_test.py b/brownie/balancer_check_balance_test.py new file mode 100644 index 0000000000..3bb6da06bc --- /dev/null +++ b/brownie/balancer_check_balance_test.py @@ -0,0 +1,161 @@ +from world import * +import math + +reth = Contract.from_explorer(RETH) + +#STD = {"from": vault_oeth_admin, "gas_price": 100} +STD = {"from": vault_oeth_admin} +BALANCER_STRATEGY = "0x1ce298Ec5FE0B1E4B04fb78d275Da6280f6e82A3" +weth_whale = "0xf04a5cc80b1e94c69b48f5ee68a08cd2f09a7c3e" +reth_whale = "0xCc9EE9483f662091a1de4795249E24aC0aC2630f" +WSTD = {"from": weth_whale} + +weth.transfer(vault_oeth_core, 1000e18, WSTD) +reth.transfer(weth_whale, 27e21, {"from": reth_whale}) +balancer_reth_strat = load_contract('balancer_strat', BALANCER_STRATEGY) + + +# MANIPULATE THE POOL +ba_vault = Contract.from_explorer("0xBA12222222228d8Ba445958a75a0704d566BF2C8") +balancerUserDataEncoder = load_contract('balancerUserData', vault_oeth_admin.address) +pool = Contract.from_explorer("0x1e19cf2d73a72ef1332c882f20534b6519be0276") +# rETH / WETH +pool_id = "0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112" +rewardPool = Contract.from_explorer("0xdd1fe5ad401d4777ce89959b7fa587e569bf125d") + +weth.approve(ba_vault, 10**50, WSTD) +reth.approve(ba_vault, 10**50, WSTD) +vault_oeth_admin.depositToStrategy(BALANCER_STRATEGY, [weth], [1000 * 1e18], {'from': STRATEGIST}) + +def print_state(state_name, print_states): + if not print_states: + return + + [token,balances,last_change] = ba_vault.getPoolTokens(pool_id) + reth_balance = balancer_reth_strat.checkBalance(reth) * reth.getExchangeRate() / 1e36 + weth_balance = balancer_reth_strat.checkBalance(weth) / 1e18 + eth_balance = balancer_reth_strat.checkBalance() / 1e18 + + # reth_balance_2 = balancer_reth_strat.checkBalance2(reth) * reth.getExchangeRate() / 1e36 + # weth_balance_2 = balancer_reth_strat.checkBalance2(weth) / 1e18 + + print("State: {0}".format(state_name)) + print("") + print("Strategy:") + print("WETH balance: {:0.2f}".format(weth_balance)) + print("RETH balance (normalized exhange rate): {:0.2f}".format(reth_balance)) + print("Combined ETH balance: {:0.2f}".format(reth_balance + weth_balance)) + print("ETH denominated balance: {:0.2f}".format(eth_balance)) + # print("WETH balance 2: {:0.2f}".format(weth_balance_2)) + # print("RETH balance 2(normalized exhange rate): {:0.2f}".format(reth_balance_2)) + # print("Combined ETH balance 2: {:0.2f}".format(reth_balance_2 + weth_balance_2)) + # print("Total asset balance: {:0.2f}".format(balancer_reth_strat.checkBalance() / 1e18)) + print("BPT balance: {:0.2f}".format(rewardPool.balanceOf(balancer_reth_strat) / 1e18)) + print("") + print("Pool:") + pool_reth = balances[0] * reth.getExchangeRate() / 1e36 + pool_weth = balances[1] / 1e18 + print("balances reth(normalized)/weth: {:0.2f}/{:0.2f}".format(pool_reth, pool_weth)) + print("tvl: {:0.2f}".format(pool_reth + pool_weth)) + print("") + print("Whale") + bpt_balance = pool.balanceOf(weth_whale) + print("bpt_balance: {:0.2f}".format(bpt_balance / 1e18)) + print("WETH balance: {:0.2f}".format(weth.balanceOf(weth_whale) / 1e18)) + print("") + +def mint(amount, asset=weth): + asset.approve(oeth_vault_core, 1e50, WSTD) + oeth_vault_admin.setAssetDefaultStrategy(asset, balancer_reth_strat, {"from": timelock}) + + oeth_vault_core.mint(asset.address, amount * math.pow(10, asset.decimals()), 0, WSTD) + oeth_vault_core.allocate(WSTD) + oeth_vault_core.rebase(WSTD) + +def redeem(amount): + oeth.approve(oeth_vault_core, 1e50, WSTD) + oeth_vault_core.redeem(amount*1e18, amount*1e18*0.95, WSTD) + oeth_vault_core.rebase(WSTD) + +def deposit_withdrawal_test(amount, print_states = False): + print_state("initial state", print_states) + + # mint(400, weth) + # print_state("whale minted", print_states) + + vault_value_checker.takeSnapshot(STD) + + weth_balance_before_whale = weth.balanceOf(weth_whale) + # Enter the pool + ba_vault.joinPool( + pool_id, + weth_whale, #sender + weth_whale, #recipient + [ + # tokens need to be sorted numerically + [reth.address, weth.address], # assets + # indexes match above assets + [0, amount * 10**18], # min amounts in + balancerUserDataEncoder.userDataExactTokenInForBPTOut.encode_input(1, [0, amount * 10**18], amount * 10**18 * 0.85)[10:], + False, #fromInternalBalance + ], + WSTD + ) + + print_state("after manipulation", print_states) + + ## attempt to mint - fails with Bal208 -> BPT_OUT_MIN_AMOUNT (Slippage/front-running protection check failed on a pool join) + #mint(1, weth) + ## attempt to redeem + #redeem(400) + + bpt_balance = pool.balanceOf(weth_whale) + pool.approve(ba_vault, 10**50, WSTD) + + ba_vault.exitPool( + pool_id, + weth_whale, #sender + weth_whale, #recipient + [ + # tokens need to be sorted numerically + # we should account for some slippage here since it comes down to balance amounts in the pool + [reth.address, weth.address], # assets + #[0, 177_972 * 10**18], # min amounts out + [0, 0], # min amounts out - no MEWS on local network no need to calculate exaclty + balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(0, bpt_balance, 1)[10:], + False, #fromInternalBalance + ], + WSTD + ) + + weth_balance_diff_whale = (weth_balance_before_whale - weth.balanceOf(weth_whale))/weth_balance_before_whale + + vault_value_checker.checkDelta(0, 0.5*10**18, 0, 0.5*10**18, STD) + print_state("after exit", print_states) + + return { + "whale_weth_diff": weth_balance_diff_whale + } + +with TemporaryFork(): + stats = deposit_withdrawal_test(200_000, True) + +# plot results +# import matplotlib.pyplot as plt +# import numpy as np + +# x = range (2_000, 200_000, 5_000) +# y = [] +# for amount in x: +# with TemporaryFork(): +# stats = deposit_withdrawal_test(amount, True) +# y.append(stats["whale_weth_diff"]) +# print("stats", stats["whale_weth_diff"]) + +# # X axis parameter: +# xaxis = np.array(x) +# # Y axis parameter: +# yaxis = np.array(y) + +# plt.plot(xaxis, yaxis) +# plt.show() \ No newline at end of file diff --git a/brownie/playingAround.py b/brownie/balancer_deposit_withdrawal_test.py similarity index 100% rename from brownie/playingAround.py rename to brownie/balancer_deposit_withdrawal_test.py diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 13fff9526c..acae0344ce 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -438,4 +438,40 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { asset.safeApprove(address(balancerVault), 0); asset.safeApprove(address(balancerVault), type(uint256).max); } + + /** + * @notice Returns the rate supplied by the Balancer configured rate + * provider. Rate is used to normalize the token to common underlying + * pool denominator. (ETH for ETH Liquid staking derivatives) + * + * @param _asset Address of the Balancer pool asset + * @return rate of the corresponding asset + */ + function getRateProviderRate(address _asset) + internal + view + override + returns (uint256) + { + IMetaStablePool pool = IMetaStablePool(platformAddress); + IRateProvider[] memory providers = pool.getRateProviders(); + (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( + balancerPoolId + ); + + uint256 providersLength = providers.length; + for (uint256 i = 0; i < providersLength; ++i) { + // _assets and corresponding rate providers are all in the same order + if (address(tokens[i]) == _asset) { + // rate provider doesn't exist, defaults to 1e18 + if (address(providers[i]) == address(0)) { + return 1e18; + } + return providers[i].getRate(); + } + } + + // should never happen + assert(false); + } } diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index ff1daa267d..dc420d7baa 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -97,9 +97,18 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { /** * @notice Get strategy's share of an assets in the Balancer pool. - * This is not the value (OSUD or ETH) of the assets in the Balancer pool. + * This is not denominated in OUSD/ETH value of the assets in the Balancer pool. * @param _asset Address of the Vault collateral asset * @return amount the amount of vault collateral assets + * + * @dev it is important that this function is not affected by reporting inflated + * values of assets in case of any pool manipulation. Such a manipulation could easily + * exploit the protocol by: + * - minting OETH + * - tilting Balancer pool to report higher balances of assets + * - rebasing() -> all that extra token balances get distributed to OETH holders + * - tilting pool back + * - redeeming OETH */ function checkBalance(address _asset) external @@ -109,27 +118,42 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { returns (uint256 amount) { // Get the total balance of each of the Balancer pool assets - (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault - .getPoolTokens(balancerPoolId); - - // The strategy's shares of the assets in the Balancer pool - // denominated in 1e18. (1e18 == 100%) - uint256 strategyShare = _getBalancerPoolTokens().divPrecisely( - IERC20(platformAddress).totalSupply() + (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( + balancerPoolId ); - for (uint256 i = 0; i < balances.length; ++i) { - address poolAsset = toPoolAsset(_asset); - if (address(tokens[i]) == poolAsset) { - // convert Balancer pool asset amount to Vault asset amount. - // eg wstETH -> stETH or sfrxETH -> frxETH - (, amount) = fromPoolAsset( - poolAsset, - balances[i].mulTruncate(strategyShare) - ); - return amount; + uint256 bptBalance = _getBalancerPoolTokens(); + + // sum of all of the token's inverted rates + uint256 invertedRateAccumulator = 0; + // queried asset inverted rate + uint256 assetInvertedRate = 0; + uint256 assetRate = 0; + for (uint256 i = 0; i < tokens.length; ++i) { + uint256 rate = getRateProviderRate(address(tokens[i])); + uint256 rateInverted = uint256(1e18).divPrecisely(rate); + invertedRateAccumulator += rateInverted; + if (toPoolAsset(_asset) == address(tokens[i])) { + assetInvertedRate = rateInverted; + assetRate = rate; } } + + /* To calculate the worth of queried asset in accordance with pool token + * rates (provided by asset rateProvider) + * - convert complete balance of BPT to underlying tokens ETH denominated amount + * - take in consideration pool's tokens and their exchangeRates. For the queried asset + * deduce what a share of that asset should be in the pool in case of pool being + * completely balanced. To get to this we are using inverted exchange rate accumulator + * and queried asset inverted exchange rate. + * - divide the amount of the previous step with assetRate to convert the ETH + * denominated representation to asset denominated + */ + amount = ((bptBalance.mulTruncate( + IRateProvider(platformAddress).getRate() + ) * assetInvertedRate) / invertedRateAccumulator).divPrecisely( + assetRate + ); } /** @@ -418,4 +442,10 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { pToken.safeApprove(address(balancerVault), 0); pToken.safeApprove(address(balancerVault), type(uint256).max); } + + function getRateProviderRate(address _asset) + internal + view + virtual + returns (uint256); } From b120330d8eeb852d4f0ae7afc002d2fd0b6b897e Mon Sep 17 00:00:00 2001 From: Nick Addison Date: Thu, 3 Aug 2023 07:42:11 +1000 Subject: [PATCH 22/67] Balancer fork tests (#1727) * Added large withdraw tests for Balancer strategy * fix test log * Balancer withdraw to handle close to BPT limit * Small change to Balancer withdraw fork test * add some comments * change implementation --------- Co-authored-by: Domen Grabec --- .../strategies/balancer/BaseAuraStrategy.sol | 8 +- contracts/test/_fixture.js | 38 ++- .../balancerMetaStablePool.fork-test.js | 235 +++++++++++++++++- 3 files changed, 260 insertions(+), 21 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index a2e2115ef7..57c3c49a9e 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.0; * @title OETH Base Balancer Abstract Strategy * @author Origin Protocol Inc */ + import { BaseBalancerStrategy } from "./BaseBalancerStrategy.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; @@ -89,7 +90,9 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { * the Aura rewards pool to this strategy contract. */ function _lpWithdrawAll() internal virtual override { - uint256 bptBalance = IERC4626(auraRewardPoolAddress).balanceOf( + // Get all the strategy's BPTs in Aura + // maxRedeem is implemented as balanceOf(address) in Aura + uint256 bptBalance = IERC4626(auraRewardPoolAddress).maxRedeem( address(this) ); @@ -123,7 +126,8 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { { balancerPoolTokens = IERC20(platformAddress).balanceOf(address(this)) + - IERC4626(auraRewardPoolAddress).balanceOf(address(this)); + // maxRedeem is implemented as balanceOf(address) in Aura + IERC4626(auraRewardPoolAddress).maxRedeem(address(this)); } function _approveBase() internal virtual override { diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 913a946521..be41f40c06 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -184,6 +184,7 @@ const defaultFixture = deployments.createFixture(async () => { LUSDMetaStrategy, oethHarvester, oethDripper, + oethZapper, swapper, mockSwapper, swapper1Inch, @@ -297,6 +298,8 @@ const defaultFixture = deployments.createFixture(async () => { oethDripperProxy.address ); + oethZapper = await ethers.getContract("OETHZapper"); + // Replace OracelRouter to disable staleness const dMockOracleRouterNoStale = await deployWithConfirmation( "MockOracleRouterNoStale" @@ -558,6 +561,7 @@ const defaultFixture = deployments.createFixture(async () => { ConvexEthMetaStrategy, oethDripper, oethHarvester, + oethZapper, swapper, mockSwapper, swapper1Inch, @@ -834,18 +838,20 @@ async function convexVaultFixture() { /** * Configure a Vault with the balancerREthStrategy */ -function balancerREthFixtureSetup() { +function balancerREthFixtureSetup(config = { defaultStrategy: true }) { return deployments.createFixture(async () => { const fixture = await defaultFixture(); const { oethVault, timelock, weth, reth, balancerREthStrategy, josh } = fixture; - await oethVault - .connect(timelock) - .setAssetDefaultStrategy(reth.address, balancerREthStrategy.address); - await oethVault - .connect(timelock) - .setAssetDefaultStrategy(weth.address, balancerREthStrategy.address); + if (config.defaultStrategy) { + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(reth.address, balancerREthStrategy.address); + await oethVault + .connect(timelock) + .setAssetDefaultStrategy(weth.address, balancerREthStrategy.address); + } fixture.rEthBPT = await ethers.getContractAt( "IERC20Metadata", @@ -854,12 +860,30 @@ function balancerREthFixtureSetup() { ); fixture.balancerREthPID = balancer_rETH_WETH_PID; + fixture.auraPool = await ethers.getContractAt( + "IERC4626", + addresses.mainnet.rETH_WETH_AuraRewards + ); + fixture.balancerVault = await ethers.getContractAt( "IBalancerVault", addresses.mainnet.balancerVault, josh ); + // Get some rETH from most loaded contracts/wallets + await impersonateAndFundAddress( + addresses.mainnet.rETH, + [ + "0xCc9EE9483f662091a1de4795249E24aC0aC2630f", + "0xC6424e862f1462281B0a5FAc078e4b63006bDEBF", + "0x7d6149aD9A573A6E2Ca6eBf7D4897c1B766841B4", + "0x7C5aaA2a20b01df027aD032f7A768aC015E77b86", + "0x1BeE69b7dFFfA4E2d53C2a2Df135C388AD25dCD2", + ], + josh.getAddress() + ); + return fixture; }); } diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 9418b05938..ce18c8db65 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -1,5 +1,5 @@ const { expect } = require("chai"); -const { formatUnits } = require("ethers/lib/utils"); +const { formatUnits, parseUnits } = require("ethers").utils; const { BigNumber } = require("ethers"); const addresses = require("../../utils/addresses"); @@ -14,7 +14,12 @@ const { const log = require("../../utils/logger")("test:fork:strategy:balancer"); -const balancerREthFixture = balancerREthFixtureSetup(); +const balancerREthFixture = balancerREthFixtureSetup({ + defaultStrategy: true, +}); +const noDefaultBalancerREthFixture = balancerREthFixtureSetup({ + defaultStrategy: false, +}); const balancerWstEthFixture = balancerWstEthFixtureSetup(); forkOnlyDescribe( @@ -25,9 +30,6 @@ forkOnlyDescribe( // this.retries(3); let fixture; - beforeEach(async () => { - fixture = await balancerREthFixture(); - }); after(async () => { // This is needed to revert fixtures @@ -38,6 +40,9 @@ forkOnlyDescribe( }); describe("Post deployment", () => { + beforeEach(async () => { + fixture = await balancerREthFixture(); + }); it("Should have the correct initial state", async function () { const { balancerREthStrategy, oethVault } = fixture; @@ -88,13 +93,7 @@ forkOnlyDescribe( describe("Deposit", function () { beforeEach(async () => { - const { timelock, reth, weth, oethVault } = fixture; - await oethVault - .connect(timelock) - .setAssetDefaultStrategy(reth.address, addresses.zero); - await oethVault - .connect(timelock) - .setAssetDefaultStrategy(weth.address, addresses.zero); + fixture = await noDefaultBalancerREthFixture(); }); it("Should deposit 5 WETH and 5 rETH in Balancer MetaStablePool strategy", async function () { const { reth, rEthBPT, weth } = fixture; @@ -172,6 +171,7 @@ forkOnlyDescribe( describe("Withdraw", function () { beforeEach(async () => { + fixture = await noDefaultBalancerREthFixture(); const { balancerREthStrategy, oethVault, strategist, reth, weth } = fixture; @@ -295,7 +295,218 @@ forkOnlyDescribe( it("Should be able to withdraw with higher withdrawal slippage", async function () {}); }); + describe("Large withdraw", function () { + const depositAmount = 30000; + let depositAmountUnits, oethVaultSigner; + beforeEach(async () => { + fixture = await noDefaultBalancerREthFixture(); + const { + balancerREthStrategy, + balancerREthPID, + balancerVault, + josh, + oethVault, + oethZapper, + strategist, + reth, + weth, + } = fixture; + + oethVaultSigner = await impersonateAndFundContract(oethVault.address); + + await getPoolBalances(balancerVault, balancerREthPID); + + // Mint 100k oETH using WETH + depositAmountUnits = oethUnits(depositAmount.toString()); + await oethZapper.connect(josh).deposit({ value: depositAmountUnits }); + + // Mint 100k of oETH using RETH + await reth.connect(josh).approve(oethVault.address, depositAmountUnits); + await oethVault.connect(josh).mint(reth.address, depositAmountUnits, 0); + + await oethVault + .connect(strategist) + .depositToStrategy( + balancerREthStrategy.address, + [weth.address, reth.address], + [depositAmountUnits, depositAmountUnits] + ); + + log( + `Vault deposited ${depositAmount} WETH and ${depositAmount} RETH to Balancer strategy` + ); + }); + it(`withdraw all ${depositAmount} of both assets together using withdrawAll`, async () => { + const { balancerREthStrategy, oethVault } = fixture; + + const stratValueBefore = await oethVault.totalValue(); + log(`Vault total value before: ${formatUnits(stratValueBefore)}`); + + // Withdraw all + await balancerREthStrategy.connect(oethVaultSigner).withdrawAll(); + log(`Vault withdraws all WETH and RETH`); + + const stratValueAfter = await oethVault.totalValue(); + log(`Vault total value after: ${formatUnits(stratValueAfter)}`); + + const diff = stratValueBefore.sub(stratValueAfter); + const baseUnits = depositAmountUnits.mul(2); + const diffPercent = diff.mul(100000000).div(baseUnits); + log( + `Vault's ETH value change: ${formatUnits(diff)} ETH ${formatUnits( + diffPercent, + 6 + )}%` + ); + }); + it(`withdraw close to ${depositAmount} of both assets using multi asset withdraw`, async () => { + const { + auraPool, + balancerREthStrategy, + rEthBPT, + oethVault, + reth, + weth, + } = fixture; + + const withdrawAmount = 29950; + const withdrawAmountUnits = oethUnits(withdrawAmount.toString(), 18); + + const stratValueBefore = await oethVault.totalValue(); + log(`Vault total value before: ${formatUnits(stratValueBefore)}`); + + // Withdraw all + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( + oethVault.address, + [weth.address, reth.address], + [withdrawAmountUnits, withdrawAmountUnits] + ); + log( + `Vault withdraws ${withdrawAmount} WETH and ${withdrawAmount} RETH together` + ); + + const bptAfterReth = await auraPool.balanceOf( + balancerREthStrategy.address + ); + log(`Aura BPTs after withdraw: ${formatUnits(bptAfterReth)}`); + log( + `Strategy BPTs after withdraw: ${formatUnits( + await rEthBPT.balanceOf(balancerREthStrategy.address) + )}` + ); + + const stratValueAfter = await oethVault.totalValue(); + log(`Vault total value after: ${formatUnits(stratValueAfter)}`); + + const diff = stratValueBefore.sub(stratValueAfter); + const baseUnits = withdrawAmountUnits.mul(2); + const diffPercent = diff.mul(100000000).div(baseUnits); + log( + `Vault's ETH value change: ${formatUnits(diff)} ETH ${formatUnits( + diffPercent, + 6 + )}%` + ); + }); + it(`withdraw ${depositAmount} of each asset in separate calls`, async () => { + const { + balancerREthStrategy, + rEthBPT, + oethVault, + timelock, + reth, + weth, + auraPool, + } = fixture; + + const stratValueBefore = await oethVault.totalValue(); + log(`Vault total value before: ${formatUnits(stratValueBefore)}`); + + const bptBefore = await auraPool.balanceOf( + balancerREthStrategy.address + ); + log(`Aura BPTs before: ${formatUnits(bptBefore)}`); + + const withdrawAmount = 29800; + const withdrawAmountUnits = oethUnits(withdrawAmount.toString(), 18); + + await balancerREthStrategy + .connect(timelock) + .setMaxWithdrawalSlippage(parseUnits("1", 16)); // 1% + + // Withdraw WETH + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( + oethVault.address, + weth.address, + withdrawAmountUnits + ); + + log(`Vault withdraws ${withdrawAmount} WETH`); + + const stratValueAfterWeth = await oethVault.totalValue(); + log( + `Vault total value after WETH withdraw: ${formatUnits( + stratValueAfterWeth + )}` + ); + const bptAfterWeth = await auraPool.balanceOf( + balancerREthStrategy.address + ); + log(`Aura BPTs after WETH withdraw: ${formatUnits(bptAfterWeth)}`); + log( + `Strategy BPTs after WETH withdraw: ${formatUnits( + await rEthBPT.balanceOf(balancerREthStrategy.address) + )}` + ); + + // Withdraw RETH + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( + oethVault.address, + reth.address, + withdrawAmountUnits + ); + + log(`Vault withdraws ${withdrawAmount} RETH`); + + const bptAfterReth = await auraPool.balanceOf( + balancerREthStrategy.address + ); + log(`Aura BPTs after RETH withdraw: ${formatUnits(bptAfterReth)}`); + log( + `Strategy BPTs after RETH withdraw: ${formatUnits( + await rEthBPT.balanceOf(balancerREthStrategy.address) + )}` + ); + + const stratValueAfterReth = await oethVault.totalValue(); + log( + `Vault total value after RETH withdraw: ${formatUnits( + stratValueAfterReth + )}` + ); + + const diff = stratValueBefore.sub(stratValueAfterReth); + const baseUnits = withdrawAmountUnits.mul(2); + const diffPercent = diff.mul(100000000).div(baseUnits); + log( + `Vault's ETH value change: ${formatUnits(diff)} ETH ${formatUnits( + diffPercent, + 6 + )}%` + ); + }); + }); + describe("Harvest rewards", function () { + beforeEach(async () => { + fixture = await balancerREthFixture(); + }); it("Should be able to collect reward tokens", async function () { const { josh, balancerREthStrategy, oethHarvester } = fixture; From 39a7b3ff49cda99be495034127f5b233bb39488e Mon Sep 17 00:00:00 2001 From: Shahul Hameed <10547529+shahthepro@users.noreply.github.com> Date: Thu, 3 Aug 2023 02:11:33 +0400 Subject: [PATCH 23/67] Add read-only reentrancy test (#1731) * Added large withdraw tests for Balancer strategy * fix test log * Balancer withdraw to handle close to BPT limit * Small change to Balancer withdraw fork test * add some comments * Add test for read-only reentrancy * add reentrancy protection to checkBalance functions * add documentation * remove the only --------- Co-authored-by: Nicholas Addison Co-authored-by: Domen Grabec --- .../mocks/MockEvilReentrantContract.sol | 141 ++++++++++++++++++ .../strategies/balancer/BaseAuraStrategy.sol | 2 +- .../balancer/BaseBalancerStrategy.sol | 15 +- contracts/test/_fixture.js | 4 +- .../balancerPoolReentrancy.fork-test.js | 73 +++++++++ 5 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 contracts/contracts/mocks/MockEvilReentrantContract.sol create mode 100644 contracts/test/strategies/balancerPoolReentrancy.fork-test.js diff --git a/contracts/contracts/mocks/MockEvilReentrantContract.sol b/contracts/contracts/mocks/MockEvilReentrantContract.sol new file mode 100644 index 0000000000..0ede2da343 --- /dev/null +++ b/contracts/contracts/mocks/MockEvilReentrantContract.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IVault } from "../interfaces/IVault.sol"; +import { IOracle } from "../interfaces/IOracle.sol"; +import { IRateProvider } from "../interfaces/balancer/IRateProvider.sol"; + +import { IBalancerVault } from "../interfaces/balancer/IBalancerVault.sol"; +import { IERC20 } from "../utils/InitializableAbstractStrategy.sol"; + +import { StableMath } from "../utils/StableMath.sol"; + +import "hardhat/console.sol"; + +contract MockEvilReentrantContract { + using StableMath for uint256; + + IBalancerVault public immutable balancerVault; + IERC20 public immutable reth; + IERC20 public immutable weth; + IVault public immutable oethVault; + address public immutable poolAddress; + bytes32 public immutable balancerPoolId; + + constructor( + address _balancerVault, + address _oethVault, + address _reth, + address _weth, + address _poolAddress, + bytes32 _poolId + ) { + balancerVault = IBalancerVault(_balancerVault); + oethVault = IVault(_oethVault); + reth = IERC20(_reth); + weth = IERC20(_weth); + poolAddress = _poolAddress; + balancerPoolId = _poolId; + } + + function doEvilStuff() public { + address priceProvider = oethVault.priceProvider(); + uint256 rethPrice = IOracle(priceProvider).price(address(reth)); + + // 1. Join pool + uint256[] memory amounts = new uint256[](2); + amounts[0] = uint256(10 ether); + amounts[1] = rethPrice * 10; + + address[] memory assets = new address[](2); + assets[0] = address(reth); + assets[1] = address(weth); + + uint256 minBPT = getBPTExpected(assets, amounts).mulTruncate( + 0.99 ether + ); + + bytes memory joinUserData = abi.encode( + IBalancerVault.WeightedPoolJoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, + amounts, + minBPT + ); + + IBalancerVault.JoinPoolRequest memory joinRequest = IBalancerVault + .JoinPoolRequest(assets, amounts, joinUserData, false); + + balancerVault.joinPool( + balancerPoolId, + address(this), + address(this), + joinRequest + ); + + uint256 bptTokenBalance = IERC20(poolAddress).balanceOf(address(this)); + console.log("BPT Token balance: %s", bptTokenBalance); + + // 2. Redeem as ETH + bytes memory exitUserData = abi.encode( + IBalancerVault.WeightedPoolExitKind.EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, + bptTokenBalance, + 1 + ); + + assets[1] = address(0); // Receive ETH instead of WETH + uint256[] memory exitAmounts = new uint256[](2); + exitAmounts[1] = 15 ether; + IBalancerVault.ExitPoolRequest memory exitRequest = IBalancerVault + .ExitPoolRequest(assets, exitAmounts, exitUserData, false); + + balancerVault.exitPool( + balancerPoolId, + address(this), + payable(address(this)), + exitRequest + ); + bptTokenBalance = IERC20(poolAddress).balanceOf(address(this)); + console.log("BPT Token balance: %s", bptTokenBalance); + } + + function getBPTExpected(address[] memory _assets, uint256[] memory _amounts) + internal + view + virtual + returns (uint256 bptExpected) + { + // Get the oracle from the OETH Vault + address priceProvider = oethVault.priceProvider(); + + for (uint256 i = 0; i < _assets.length; ++i) { + uint256 strategyAssetMarketPrice = IOracle(priceProvider).price( + _assets[i] + ); + // convert asset amount to ETH amount + bptExpected = + bptExpected + + _amounts[i].mulTruncate(strategyAssetMarketPrice); + } + + uint256 bptRate = IRateProvider(poolAddress).getRate(); + // Convert ETH amount to BPT amount + bptExpected = bptExpected.divPrecisely(bptRate); + } + + function approveAllTokens() public { + // Approve all tokens + weth.approve(address(oethVault), type(uint256).max); + reth.approve(poolAddress, type(uint256).max); + weth.approve(poolAddress, type(uint256).max); + reth.approve(address(balancerVault), type(uint256).max); + weth.approve(address(balancerVault), type(uint256).max); + } + + receive() external payable { + console.log("Received ETH"); + + // 3. Try to mint OETH + oethVault.mint(address(weth), 1 ether, 0.9 ether); + + console.log("You shouldn't see me!!!"); + } +} diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 57c3c49a9e..4637c4d5b5 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -84,7 +84,7 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { true // also claim reward tokens ); } - + /** * @dev Withdraw all Balancer Pool Tokens (BPT) from * the Aura rewards pool to this strategy contract. diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index dc420d7baa..2ccccb1811 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -101,6 +101,9 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * @param _asset Address of the Vault collateral asset * @return amount the amount of vault collateral assets * + * IMPORTANT if this function is overridden it needs to have a whenNotInVaultContext + * modifier on it or it is susceptible to read-only re-entrancy attack + * * @dev it is important that this function is not affected by reporting inflated * values of assets in case of any pool manipulation. Such a manipulation could easily * exploit the protocol by: @@ -115,6 +118,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { view virtual override + whenNotInVaultContext returns (uint256 amount) { // Get the total balance of each of the Balancer pool assets @@ -161,8 +165,17 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * Uses the Balancer pool's rate (virtual price) to convert the strategy's * Balancer Pool Tokens (BPT) to ETH value. * @return value The ETH value + * + * IMPORTANT if this function is overridden it needs to have a whenNotInVaultContext + * modifier on it or it is susceptible to read-only re-entrancy attack */ - function checkBalance() external view virtual returns (uint256 value) { + function checkBalance() + external + view + virtual + whenNotInVaultContext + returns (uint256 value) + { uint256 bptBalance = _getBalancerPoolTokens(); // Convert BPT to ETH value diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index be41f40c06..5d9986f4c8 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -1298,7 +1298,9 @@ async function impersonateAndFundContract(address, amount = "100000") { await _hardhatSetBalance(address, amount); - return await ethers.provider.getSigner(address); + const signer = await ethers.provider.getSigner(address); + signer.address = address; + return signer; } async function impersonateAndFundAddress( diff --git a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js new file mode 100644 index 0000000000..eba99a3b5a --- /dev/null +++ b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js @@ -0,0 +1,73 @@ +const hre = require("hardhat"); +const { ethers } = hre; +const { expect } = require("chai"); +const { forkOnlyDescribe } = require("../helpers"); +const { + defaultFixtureSetup, + balancerREthFixtureSetup, + mintWETH, + impersonateAndFundContract, +} = require("../_fixture"); +const { deployWithConfirmation } = require("../../utils/deploy"); +const { utils } = require("ethers"); +const { findBestMainnetTokenHolder } = require("../../utils/funding"); +const addresses = require("../../utils/addresses"); + +const balancerREthFixture = balancerREthFixtureSetup({ + defaultStrategy: true, +}); + +forkOnlyDescribe( + "ForkTest: Balancer MetaStablePool - Read-only Reentrancy", + function () { + this.timeout(0); + + after(async () => { + // This is needed to revert fixtures + // The other tests as of now don't use proper fixtures + // Rel: https://github.com/OriginProtocol/origin-dollar/issues/1259 + const f = defaultFixtureSetup(); + await f(); + }); + + it("Should not allow read-only reentrancy", async () => { + const { weth, reth, oethVault, rEthBPT, balancerREthPID, daniel } = + await balancerREthFixture(); + + // Deploy the attacking contract + const dEvilContract = await deployWithConfirmation( + "MockEvilReentrantContract", + [ + addresses.mainnet.balancerVault, + oethVault.address, + reth.address, + weth.address, + rEthBPT.address, + balancerREthPID, + ] + ); + const cEvilContract = await ethers.getContractAt( + "MockEvilReentrantContract", + dEvilContract.address + ); + + // Approve movement of tokens + await cEvilContract.connect(daniel).approveAllTokens(); + + // Fund the attacking contract with WETH + await mintWETH( + weth, + await impersonateAndFundContract(cEvilContract.address), + "100000" + ); + // ... and rETH + const rethHolder = await findBestMainnetTokenHolder(reth, hre); + await reth + .connect(rethHolder) + .transfer(cEvilContract.address, utils.parseEther("1000")); + + // Do Evil Stuff + await expect(cEvilContract.doEvilStuff()).to.be.reverted; + }); + } +); From 346d9499e27e2912fbd85167838fe4b8c008f362 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 3 Aug 2023 22:57:05 +0200 Subject: [PATCH 24/67] Balancer fixes (#1734) * prettier * adjust how checkBalance is calculated --- .../strategies/balancer/BaseAuraStrategy.sol | 2 +- .../balancer/BaseBalancerStrategy.sol | 41 ++++++++----------- .../balancerMetaStablePool.fork-test.js | 2 +- contracts/utils/funding.js | 11 ++++- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 4637c4d5b5..57c3c49a9e 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -84,7 +84,7 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { true // also claim reward tokens ); } - + /** * @dev Withdraw all Balancer Pool Tokens (BPT) from * the Aura rewards pool to this strategy contract. diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 2ccccb1811..b94f6562ed 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -100,13 +100,13 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * This is not denominated in OUSD/ETH value of the assets in the Balancer pool. * @param _asset Address of the Vault collateral asset * @return amount the amount of vault collateral assets - * + * * IMPORTANT if this function is overridden it needs to have a whenNotInVaultContext - * modifier on it or it is susceptible to read-only re-entrancy attack + * modifier on it or it is susceptible to read-only re-entrancy attack * * @dev it is important that this function is not affected by reporting inflated * values of assets in case of any pool manipulation. Such a manipulation could easily - * exploit the protocol by: + * exploit the protocol by: * - minting OETH * - tilting Balancer pool to report higher balances of assets * - rebasing() -> all that extra token balances get distributed to OETH holders @@ -128,21 +128,6 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256 bptBalance = _getBalancerPoolTokens(); - // sum of all of the token's inverted rates - uint256 invertedRateAccumulator = 0; - // queried asset inverted rate - uint256 assetInvertedRate = 0; - uint256 assetRate = 0; - for (uint256 i = 0; i < tokens.length; ++i) { - uint256 rate = getRateProviderRate(address(tokens[i])); - uint256 rateInverted = uint256(1e18).divPrecisely(rate); - invertedRateAccumulator += rateInverted; - if (toPoolAsset(_asset) == address(tokens[i])) { - assetInvertedRate = rateInverted; - assetRate = rate; - } - } - /* To calculate the worth of queried asset in accordance with pool token * rates (provided by asset rateProvider) * - convert complete balance of BPT to underlying tokens ETH denominated amount @@ -153,11 +138,19 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * - divide the amount of the previous step with assetRate to convert the ETH * denominated representation to asset denominated */ - amount = ((bptBalance.mulTruncate( + amount = (bptBalance.mulTruncate( IRateProvider(platformAddress).getRate() - ) * assetInvertedRate) / invertedRateAccumulator).divPrecisely( - assetRate - ); + ) / tokens.length); + + /* If pool asset is equals _asset it means a rate provider for that asset + * exists and that asset is not necessarily pegged to a unit (ETH). + * + * Because this function returns the balance of the asset not denominated in + * ETH units we need to convert the amount to asset amount. + */ + if (toPoolAsset(_asset) == _asset) { + amount = amount.divPrecisely(getRateProviderRate(_asset)); + } } /** @@ -165,9 +158,9 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * Uses the Balancer pool's rate (virtual price) to convert the strategy's * Balancer Pool Tokens (BPT) to ETH value. * @return value The ETH value - * + * * IMPORTANT if this function is overridden it needs to have a whenNotInVaultContext - * modifier on it or it is susceptible to read-only re-entrancy attack + * modifier on it or it is susceptible to read-only re-entrancy attack */ function checkBalance() external diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index ce18c8db65..2ce86e789c 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -429,7 +429,7 @@ forkOnlyDescribe( ); log(`Aura BPTs before: ${formatUnits(bptBefore)}`); - const withdrawAmount = 29800; + const withdrawAmount = 29700; const withdrawAmountUnits = oethUnits(withdrawAmount.toString(), 18); await balancerREthStrategy diff --git a/contracts/utils/funding.js b/contracts/utils/funding.js index 90086b36d1..e027486433 100644 --- a/contracts/utils/funding.js +++ b/contracts/utils/funding.js @@ -159,8 +159,15 @@ const fundAccounts = async () => { const ousdCoins = [dai, usdc, usdt, tusd, ogn]; const oethCoins = [weth, rETH, stETH, frxETH]; - const allCoins = [...ousdCoins, ...oethCoins]; - + const skipOUSDCoins = !!process.env.SKIP_OUSD_COINS; + const skipOETHCoins = !!process.env.SKIP_OETH_COINS; + let allCoins = []; + if (!skipOUSDCoins) { + allCoins = [...allCoins, ...ousdCoins]; + } + if (!skipOETHCoins) { + allCoins = [...allCoins, ...oethCoins]; + } const signers = await hre.ethers.getSigners(); const addressPromises = new Array(10) From fbafb803749c7f8550b2afc96bbf263b6a99f399 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Sat, 5 Aug 2023 16:01:03 +0200 Subject: [PATCH 25/67] Balancer withdrawal fix (#1739) * fix balancer withdrawals * lint * prettier --- brownie/abi/balancerUserData.json | 20 ++++++ brownie/balancer_check_balance_test.py | 66 +++++++++++++++---- .../mocks/MockEvilReentrantContract.sol | 8 --- .../balancer/BalancerMetaPoolStrategy.sol | 27 +++++++- .../balancer/BaseBalancerStrategy.sol | 26 ++++---- contracts/test/_fixture.js | 5 ++ .../balancerMetaStablePool.fork-test.js | 4 +- contracts/utils/funding.js | 4 +- 8 files changed, 120 insertions(+), 40 deletions(-) diff --git a/brownie/abi/balancerUserData.json b/brownie/abi/balancerUserData.json index b05b5894f4..e5f3432756 100644 --- a/brownie/abi/balancerUserData.json +++ b/brownie/abi/balancerUserData.json @@ -48,5 +48,25 @@ "payable": false, "stateMutability": "nonpayable", "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "joinKind", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBptAmountout", + "type": "uint256" + } + ], + "name": "userDataExactBPTinForTokensOut", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/brownie/balancer_check_balance_test.py b/brownie/balancer_check_balance_test.py index 3bb6da06bc..f83ccd8b82 100644 --- a/brownie/balancer_check_balance_test.py +++ b/brownie/balancer_check_balance_test.py @@ -77,17 +77,16 @@ def redeem(amount): oeth_vault_core.redeem(amount*1e18, amount*1e18*0.95, WSTD) oeth_vault_core.rebase(WSTD) -def deposit_withdrawal_test(amount, print_states = False): +def deposit_withdrawal_test(amount, _outputAmount, print_states = False): print_state("initial state", print_states) # mint(400, weth) # print_state("whale minted", print_states) - vault_value_checker.takeSnapshot(STD) - weth_balance_before_whale = weth.balanceOf(weth_whale) # Enter the pool - ba_vault.joinPool( + amountsIn = [amount * 10**18, amount * 10**18] + tx_join = ba_vault.joinPool( pool_id, weth_whale, #sender weth_whale, #recipient @@ -95,13 +94,13 @@ def deposit_withdrawal_test(amount, print_states = False): # tokens need to be sorted numerically [reth.address, weth.address], # assets # indexes match above assets - [0, amount * 10**18], # min amounts in - balancerUserDataEncoder.userDataExactTokenInForBPTOut.encode_input(1, [0, amount * 10**18], amount * 10**18 * 0.85)[10:], + amountsIn, # min amounts in + balancerUserDataEncoder.userDataExactTokenInForBPTOut.encode_input(1, amountsIn, amount * 10**18 * 0.9)[10:], False, #fromInternalBalance ], WSTD ) - + print_state("after manipulation", print_states) ## attempt to mint - fails with Bal208 -> BPT_OUT_MIN_AMOUNT (Slippage/front-running protection check failed on a pool join) @@ -112,7 +111,38 @@ def deposit_withdrawal_test(amount, print_states = False): bpt_balance = pool.balanceOf(weth_whale) pool.approve(ba_vault, 10**50, WSTD) - ba_vault.exitPool( + # EXACT_BPT_IN_FOR_ONE_TOKEN_OUT - single asset exit + # user data [EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, bptAmountIn, exitTokenIndex] + # ba_vault.exitPool( + # pool_id, + # weth_whale, #sender + # weth_whale, #recipient + # [ + # # tokens need to be sorted numerically + # # we should account for some slippage here since it comes down to balance amounts in the pool + # [reth.address, weth.address], # assets + # #[0, 177_972 * 10**18], # min amounts out + # [0, 0], # min amounts out - no MEWS on local network no need to calculate exaclty + # balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(0, bpt_balance, 1)[10:], + # False, #fromInternalBalance + # ], + # WSTD + # ) + + # BPT_IN_FOR_EXACT_TOKENS_OUT + # User sends an estimated but unknown (computed at run time) quantity of BPT, and receives precise quantities of specified tokens + # user data [BPT_IN_FOR_EXACT_TOKENS_OUT, amountsOut, maxBPTAmountIn] + # weth_exit_before = weth.balanceOf(weth_whale) + # reth_exit_before = reth.balanceOf(weth_whale) + + # bpt_balance = 9742858928635020293 + #outputAmounts = [_outputAmount * 10**18, _outputAmount * 10**18] + outputAmounts = [_outputAmount * 10**18, 0] + # print("OUTPUT amounts") + # print(outputAmounts[0]) + # print(outputAmounts[1]) + bpt_balance = _outputAmount * 10**18 * 1.15 + tx_exit = ba_vault.exitPool( pool_id, weth_whale, #sender weth_whale, #recipient @@ -121,24 +151,32 @@ def deposit_withdrawal_test(amount, print_states = False): # we should account for some slippage here since it comes down to balance amounts in the pool [reth.address, weth.address], # assets #[0, 177_972 * 10**18], # min amounts out - [0, 0], # min amounts out - no MEWS on local network no need to calculate exaclty - balancerUserDataEncoder.userDataTokenInExactBPTOut.encode_input(0, bpt_balance, 1)[10:], + #outputAmounts, # min amounts out - no MEWS on local network no need to calculate exaclty + [_outputAmount * 10**18 - 10**9,0], + balancerUserDataEncoder.userDataExactTokenInForBPTOut.encode_input(2, outputAmounts, bpt_balance)[10:], False, #fromInternalBalance ], WSTD ) + print("user data", balancerUserDataEncoder.userDataExactTokenInForBPTOut.encode_input(2, outputAmounts, bpt_balance)[10:]) weth_balance_diff_whale = (weth_balance_before_whale - weth.balanceOf(weth_whale))/weth_balance_before_whale - - vault_value_checker.checkDelta(0, 0.5*10**18, 0, 0.5*10**18, STD) print_state("after exit", print_states) + print("weth_balance_diff_whale", weth_balance_diff_whale) + # weth_exit_diff = weth.balanceOf(weth_whale) - weth_exit_before + # reth_exit_diff = reth.balanceOf(weth_whale) - reth_exit_before + # print("weth_exit_diff", weth_exit_diff) + # print("reth_exit_diff", reth_exit_diff) return { - "whale_weth_diff": weth_balance_diff_whale + "whale_weth_diff": weth_balance_diff_whale, + "tx_exit": tx_exit, + "tx_join": tx_join, } with TemporaryFork(): - stats = deposit_withdrawal_test(200_000, True) + #stats = deposit_withdrawal_test(10, True) + stats = deposit_withdrawal_test(10, 0.8123, True) # plot results # import matplotlib.pyplot as plt diff --git a/contracts/contracts/mocks/MockEvilReentrantContract.sol b/contracts/contracts/mocks/MockEvilReentrantContract.sol index 0ede2da343..80ee512c1a 100644 --- a/contracts/contracts/mocks/MockEvilReentrantContract.sol +++ b/contracts/contracts/mocks/MockEvilReentrantContract.sol @@ -10,8 +10,6 @@ import { IERC20 } from "../utils/InitializableAbstractStrategy.sol"; import { StableMath } from "../utils/StableMath.sol"; -import "hardhat/console.sol"; - contract MockEvilReentrantContract { using StableMath for uint256; @@ -72,7 +70,6 @@ contract MockEvilReentrantContract { ); uint256 bptTokenBalance = IERC20(poolAddress).balanceOf(address(this)); - console.log("BPT Token balance: %s", bptTokenBalance); // 2. Redeem as ETH bytes memory exitUserData = abi.encode( @@ -94,7 +91,6 @@ contract MockEvilReentrantContract { exitRequest ); bptTokenBalance = IERC20(poolAddress).balanceOf(address(this)); - console.log("BPT Token balance: %s", bptTokenBalance); } function getBPTExpected(address[] memory _assets, uint256[] memory _amounts) @@ -131,11 +127,7 @@ contract MockEvilReentrantContract { } receive() external payable { - console.log("Received ETH"); - // 3. Try to mint OETH oethVault.mint(address(weth), 1 ether, 0.9 ether); - - console.log("You shouldn't see me!!!"); } } diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index acae0344ce..db7a625229 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -247,6 +247,19 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { _amounts[j] ); wrappedAssetAmounts[j] = poolAmountsOut[i]; + + /* Because of the potential Balancer rounding error mentioned below + * the contract might receive 1-2 WEI smaller amount than required + * in the withdraw user data encoding. If slightly lesser token amount + * is received the strategy can not unwrap the pool asset as it is + * smaller than expected. + * + * For that reason we `overshoot` the required tokens expected to + * circumvent the error + */ + if (poolAmountsOut[i] > 0) { + poolAmountsOut[i] += 2; + } } } } @@ -267,7 +280,19 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { ); IBalancerVault.ExitPoolRequest memory request = IBalancerVault - .ExitPoolRequest(poolAssets, poolAmountsOut, userData, false); + .ExitPoolRequest( + poolAssets, + /* We specify the exact amount of a tokens we are expecting in the encoded + * userData, for that reason we don't need to specify the amountsOut here. + * + * Also Balancer has a rounding issue that can make a transaction fail: + * https://github.com/balancer/balancer-v2-monorepo/issues/2541 + * which is an extra reason why this field is empty. + */ + new uint256[](tokens.length), + userData, + false + ); balancerVault.exitPool( balancerPoolId, diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index b94f6562ed..0475c44948 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -121,32 +121,30 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { whenNotInVaultContext returns (uint256 amount) { - // Get the total balance of each of the Balancer pool assets (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( balancerPoolId ); uint256 bptBalance = _getBalancerPoolTokens(); - /* To calculate the worth of queried asset in accordance with pool token - * rates (provided by asset rateProvider) - * - convert complete balance of BPT to underlying tokens ETH denominated amount - * - take in consideration pool's tokens and their exchangeRates. For the queried asset - * deduce what a share of that asset should be in the pool in case of pool being - * completely balanced. To get to this we are using inverted exchange rate accumulator - * and queried asset inverted exchange rate. - * - divide the amount of the previous step with assetRate to convert the ETH - * denominated representation to asset denominated + /* To calculate the worth of queried asset: + * - assume that all tokens normalized to their ETH value have an equal split balance + * in the pool when it is balanced + * - multiply the BPT amount with the bpt rate to get the ETH denominated amount + * of strategy's holdings + * - divide that by the number of tokens in the pool to get ETH denominated amount + * that is applicable to each token in the pool */ amount = (bptBalance.mulTruncate( IRateProvider(platformAddress).getRate() ) / tokens.length); - /* If pool asset is equals _asset it means a rate provider for that asset - * exists and that asset is not necessarily pegged to a unit (ETH). + /* If the pool asset is equal to (strategy )_asset it means that a rate + * provider for that asset exists and that asset is not necessarily + * pegged to a unit (ETH). * - * Because this function returns the balance of the asset not denominated in - * ETH units we need to convert the amount to asset amount. + * Because this function returns the balance of the asset and is not denominated in + * ETH units we need to convert the ETH denominated amount to asset amount. */ if (toPoolAsset(_asset) == _asset) { amount = amount.divPrecisely(getRateProviderRate(_asset)); diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 5d9986f4c8..f9775fba5b 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -940,6 +940,11 @@ function balancerWstEthFixtureSetup() { ); fixture.balancerWstEthPID = balancer_stETH_WETH_PID; + fixture.auraPool = await ethers.getContractAt( + "IERC4626", + addresses.mainnet.wstETH_WETH_AuraRewards + ); + fixture.balancerVault = await ethers.getContractAt( "IBalancerVault", addresses.mainnet.balancerVault, diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 2ce86e789c..8db50370e2 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -582,7 +582,7 @@ forkOnlyDescribe( .depositToStrategy( balancerWstEthStrategy.address, [weth.address, stETH.address], - [oethUnits("25"), oethUnits("25")] + [units("25", weth), oethUnits("25")] ); // TODO: Check slippage errors @@ -590,6 +590,7 @@ forkOnlyDescribe( .connect(strategist) .setMaxWithdrawalSlippage(oethUnits("0.01")); }); + it("Should be able to withdraw 10 WETH from the pool", async function () { const { weth, balancerWstEthStrategy, oethVault } = fixture; @@ -614,6 +615,7 @@ forkOnlyDescribe( ); expect(wethBalanceDiffVault).to.approxEqualTolerance(withdrawAmount, 1); }); + it("Should be able to withdraw 8 stETH from the pool", async function () { const { stETH, balancerWstEthStrategy, oethVault } = fixture; diff --git a/contracts/utils/funding.js b/contracts/utils/funding.js index e027486433..1223a43b28 100644 --- a/contracts/utils/funding.js +++ b/contracts/utils/funding.js @@ -159,8 +159,8 @@ const fundAccounts = async () => { const ousdCoins = [dai, usdc, usdt, tusd, ogn]; const oethCoins = [weth, rETH, stETH, frxETH]; - const skipOUSDCoins = !!process.env.SKIP_OUSD_COINS; - const skipOETHCoins = !!process.env.SKIP_OETH_COINS; + const skipOUSDCoins = process.env.SKIP_OUSD_COINS == "true"; + const skipOETHCoins = process.env.SKIP_OETH_COINS == "true"; let allCoins = []; if (!skipOUSDCoins) { allCoins = [...allCoins, ...ousdCoins]; From 430fbad7429f8c639d7d7f36fc48a5c4c417ac3f Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Sat, 5 Aug 2023 16:50:36 +0200 Subject: [PATCH 26/67] use only 1 safeApprove when applicable --- .../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol | 1 - contracts/contracts/strategies/balancer/BaseAuraStrategy.sol | 1 - contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol | 1 - 3 files changed, 3 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index db7a625229..fe1371ca92 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -460,7 +460,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ function _approveAsset(address _asset) internal { IERC20 asset = IERC20(_asset); - asset.safeApprove(address(balancerVault), 0); asset.safeApprove(address(balancerVault), type(uint256).max); } diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 57c3c49a9e..8aeb8dbb31 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -134,7 +134,6 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { super._approveBase(); IERC20 pToken = IERC20(platformAddress); - pToken.safeApprove(auraRewardPoolAddress, 0); pToken.safeApprove(auraRewardPoolAddress, type(uint256).max); } } diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 0475c44948..3ca0cca7da 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -443,7 +443,6 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { function _approveBase() internal virtual { IERC20 pToken = IERC20(platformAddress); // Balancer vault for BPT token (required for removing liquidity) - pToken.safeApprove(address(balancerVault), 0); pToken.safeApprove(address(balancerVault), type(uint256).max); } From 3ec984c83d45380acbb769f3934a87a0f0e2c001 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Sat, 5 Aug 2023 16:58:51 +0200 Subject: [PATCH 27/67] some renames and more correct application of approves --- .../balancer/BalancerMetaPoolStrategy.sol | 14 +++++--------- .../strategies/balancer/BaseBalancerStrategy.sol | 13 ++++++++----- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index fe1371ca92..a7ab6bb02b 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -36,7 +36,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { function deposit(address _asset, uint256 _amount) external override - whenNotInVaultContext onlyVault nonReentrant { @@ -56,7 +55,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ function deposit(address[] memory _assets, uint256[] memory _amounts) external - whenNotInVaultContext onlyVault nonReentrant { @@ -69,7 +67,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { function depositAll() external override - whenNotInVaultContext onlyVault nonReentrant { @@ -165,7 +162,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address _recipient, address _asset, uint256 _amount - ) external override whenNotInVaultContext onlyVault nonReentrant { + ) external override onlyVault nonReentrant { address[] memory assets = new address[](1); uint256[] memory amounts = new uint256[](1); assets[0] = _asset; @@ -184,7 +181,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address _recipient, address[] memory _assets, uint256[] memory _amounts - ) external whenNotInVaultContext onlyVault nonReentrant { + ) external onlyVault nonReentrant { _withdraw(_recipient, _assets, _amounts); } @@ -334,7 +331,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { function withdrawAll() external override - whenNotInVaultContext onlyVaultOrGovernor nonReentrant { @@ -445,9 +441,9 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { function _abstractSetPToken(address _asset, address) internal override { address poolAsset = toPoolAsset(_asset); if (_asset == stETH) { - IERC20(stETH).safeApprove(wstETH, 1e50); + IERC20(stETH).approve(wstETH, 1e50); } else if (_asset == frxETH) { - IERC20(frxETH).safeApprove(sfrxETH, 1e50); + IERC20(frxETH).approve(sfrxETH, 1e50); } _approveAsset(poolAsset); } @@ -460,7 +456,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ function _approveAsset(address _asset) internal { IERC20 asset = IERC20(_asset); - asset.safeApprove(address(balancerVault), type(uint256).max); + asset.approve(address(balancerVault), type(uint256).max); } /** diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 3ca0cca7da..d2ca3c1823 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -76,8 +76,11 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * * Use this modifier with any function that can cause a state change in a pool and is either public itself, * or called by a public function *outside* a Vault operation (e.g., join, exit, or swap). + * + * This is to protect against Balancer's read-only re-entrancy vulnerability: + * https://www.notion.so/originprotocol/Balancer-read-only-reentrancy-c686e72c82414ef18fa34312bb02e11b */ - modifier whenNotInVaultContext() { + modifier whenNotInBalancerVaultContext() { VaultReentrancyLib.ensureNotInVaultContext(balancerVault); _; } @@ -101,7 +104,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * @param _asset Address of the Vault collateral asset * @return amount the amount of vault collateral assets * - * IMPORTANT if this function is overridden it needs to have a whenNotInVaultContext + * IMPORTANT if this function is overridden it needs to have a whenNotInBalancerVaultContext * modifier on it or it is susceptible to read-only re-entrancy attack * * @dev it is important that this function is not affected by reporting inflated @@ -118,7 +121,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { view virtual override - whenNotInVaultContext + whenNotInBalancerVaultContext returns (uint256 amount) { (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( @@ -157,14 +160,14 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * Balancer Pool Tokens (BPT) to ETH value. * @return value The ETH value * - * IMPORTANT if this function is overridden it needs to have a whenNotInVaultContext + * IMPORTANT if this function is overridden it needs to have a whenNotInBalancerVaultContext * modifier on it or it is susceptible to read-only re-entrancy attack */ function checkBalance() external view virtual - whenNotInVaultContext + whenNotInBalancerVaultContext returns (uint256 value) { uint256 bptBalance = _getBalancerPoolTokens(); From ecceeb189d620383fab60a63770ed12919417057 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Sun, 6 Aug 2023 22:27:23 +0200 Subject: [PATCH 28/67] renames, additional requires, move initializer to a better location, slither --- .../balancer/BalancerMetaPoolStrategy.sol | 25 +++--- .../strategies/balancer/BaseAuraStrategy.sol | 34 +------- .../balancer/BaseBalancerStrategy.sol | 85 +++++++++++++------ 3 files changed, 72 insertions(+), 72 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index a7ab6bb02b..d1e924ca47 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -64,12 +64,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { /** * @notice Deposits all supported assets in this strategy contract to the Balancer pool. */ - function depositAll() - external - override - onlyVault - nonReentrant - { + function depositAll() external override onlyVault nonReentrant { uint256 assetsLength = assetsMapped.length; address[] memory assets = new address[](assetsLength); uint256[] memory amounts = new uint256[](assetsLength); @@ -86,15 +81,20 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { function _deposit(address[] memory _assets, uint256[] memory _amounts) internal { + require(_assets.length == _amounts.length, "Array length missmatch"); + (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( balancerPoolId ); uint256[] memory mappedAmounts = new uint256[](tokens.length); address[] memory mappedAssets = new address[](tokens.length); + for (uint256 i = 0; i < _assets.length; ++i) { address asset = _assets[i]; uint256 amount = _amounts[i]; + + require(supportsAsset(asset), "Unsupported asset"); mappedAssets[i] = toPoolAsset(_assets[i]); if (amount > 0) { @@ -105,7 +105,6 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { } } - // TODO move this loop into the previous loop uint256[] memory amountsIn = new uint256[](tokens.length); address[] memory poolAssets = new address[](tokens.length); for (uint256 i = 0; i < tokens.length; ++i) { @@ -328,12 +327,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { * * Is only executable by the OToken's Vault or the Governor. */ - function withdrawAll() - external - override - onlyVaultOrGovernor - nonReentrant - { + function withdrawAll() external override onlyVaultOrGovernor nonReentrant { // STEP 1 - Withdraw all Balancer Pool Tokens (BPT) from Aura to this strategy contract _lpWithdrawAll(); @@ -437,12 +431,14 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { _approveBase(); } - // solhin t-disable-next-line no-unused-vars + // solhint-disable-next-line no-unused-vars function _abstractSetPToken(address _asset, address) internal override { address poolAsset = toPoolAsset(_asset); if (_asset == stETH) { + // slither-disable-next-line unused-return IERC20(stETH).approve(wstETH, 1e50); } else if (_asset == frxETH) { + // slither-disable-next-line unused-return IERC20(frxETH).approve(sfrxETH, 1e50); } _approveAsset(poolAsset); @@ -456,6 +452,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ function _approveAsset(address _asset) internal { IERC20 asset = IERC20(_asset); + // slither-disable-next-line unused-return asset.approve(address(balancerVault), type(uint256).max); } diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 8aeb8dbb31..61cf8c81b2 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -22,44 +22,12 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { address public immutable auraRewardPoolAddress; // renamed from __reserved to not shadow BaseBalancerStrategy.__reserved, - int256[50] private __reserved_2; + int256[50] private __reserved_baseAuraStrategy; constructor(address _auraRewardPoolAddress) { auraRewardPoolAddress = _auraRewardPoolAddress; } - /** - * Initializer for setting up strategy internal state. This overrides the - * InitializableAbstractStrategy initializer as Balancer's strategies don't fit - * well within that abstraction. - * @param _rewardTokenAddresses Address of BAL & AURA - * @param _assets Addresses of supported assets. MUST be passed in the same - * order as returned by coins on the pool contract, i.e. - * WETH, stETH - * @param _pTokens Platform Token corresponding addresses - */ - function initialize( - address[] calldata _rewardTokenAddresses, // BAL & AURA - address[] calldata _assets, - address[] calldata _pTokens - ) external override onlyGovernor initializer { - maxWithdrawalSlippage = 1e15; - maxDepositSlippage = 1e15; - - IERC20[] memory poolAssets = getPoolAssets(); - require( - poolAssets.length == _assets.length, - "Pool assets length mismatch" - ); - for (uint256 i = 0; i < _assets.length; ++i) { - (address asset, ) = fromPoolAsset(address(poolAssets[i]), 0); - require(_assets[i] == asset, "Pool assets mismatch"); - } - - super._initialize(_rewardTokenAddresses, _assets, _pTokens); - _approveBase(); - } - /** * @dev Deposit all Balancer Pool Tokens (BPT) in this strategy contract * to the Aura rewards pool. diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index d2ca3c1823..1e8b620f8f 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -37,7 +37,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { // Max deposit slippage denominated in 1e18 (1e18 == 100%) uint256 public maxDepositSlippage; - int256[50] private __reserved; + int256[48] private __reserved; struct BaseBalancerConfig { address rEthAddress; // Address of the rETH token @@ -58,6 +58,22 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { uint256 _newMaxSlippagePercentage ); + /** + * @dev Ensure we are not in a Vault context when this function is called, by attempting a no-op internal + * balance operation. If we are already in a Vault transaction (e.g., a swap, join, or exit), the Vault's + * reentrancy protection will cause this function to revert. + * + * Use this modifier with any function that can cause a state change in a pool and is either public itself, + * or called by a public function *outside* a Vault operation (e.g., join, exit, or swap). + * + * This is to protect against Balancer's read-only re-entrancy vulnerability: + * https://www.notion.so/originprotocol/Balancer-read-only-reentrancy-c686e72c82414ef18fa34312bb02e11b + */ + modifier whenNotInBalancerVaultContext() { + VaultReentrancyLib.ensureNotInVaultContext(balancerVault); + _; + } + constructor(BaseBalancerConfig memory _balancerConfig) { rETH = _balancerConfig.rEthAddress; stETH = _balancerConfig.stEthAddress; @@ -70,19 +86,38 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } /** - * @dev Ensure we are not in a Vault context when this function is called, by attempting a no-op internal - * balance operation. If we are already in a Vault transaction (e.g., a swap, join, or exit), the Vault's - * reentrancy protection will cause this function to revert. - * - * Use this modifier with any function that can cause a state change in a pool and is either public itself, - * or called by a public function *outside* a Vault operation (e.g., join, exit, or swap). - * - * This is to protect against Balancer's read-only re-entrancy vulnerability: - * https://www.notion.so/originprotocol/Balancer-read-only-reentrancy-c686e72c82414ef18fa34312bb02e11b + * Initializer for setting up strategy internal state. This overrides the + * InitializableAbstractStrategy initializer as Balancer's strategies don't fit + * well within that abstraction. + * @param _rewardTokenAddresses Address of BAL & AURA + * @param _assets Addresses of supported assets. MUST be passed in the same + * order as returned by coins on the pool contract, i.e. + * WETH, stETH + * @param _pTokens Platform Token corresponding addresses */ - modifier whenNotInBalancerVaultContext() { - VaultReentrancyLib.ensureNotInVaultContext(balancerVault); - _; + function initialize( + address[] calldata _rewardTokenAddresses, // BAL & AURA + address[] calldata _assets, + address[] calldata _pTokens + ) external override onlyGovernor initializer { + maxWithdrawalSlippage = 1e15; + maxDepositSlippage = 1e15; + + emit MaxWithdrawalSlippageUpdated(0, maxWithdrawalSlippage); + emit MaxDepositSlippageUpdated(0, maxDepositSlippage); + + IERC20[] memory poolAssets = getPoolAssets(); + require( + poolAssets.length == _assets.length, + "Pool assets length mismatch" + ); + for (uint256 i = 0; i < _assets.length; ++i) { + (address asset, ) = fromPoolAsset(address(poolAssets[i]), 0); + require(_assets[i] == asset, "Pool assets mismatch"); + } + + super._initialize(_rewardTokenAddresses, _assets, _pTokens); + _approveBase(); } /** @@ -124,10 +159,6 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { whenNotInBalancerVaultContext returns (uint256 amount) { - (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( - balancerPoolId - ); - uint256 bptBalance = _getBalancerPoolTokens(); /* To calculate the worth of queried asset: @@ -135,12 +166,17 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * in the pool when it is balanced * - multiply the BPT amount with the bpt rate to get the ETH denominated amount * of strategy's holdings - * - divide that by the number of tokens in the pool to get ETH denominated amount - * that is applicable to each token in the pool + * - divide that by the number of tokens we support in the pool to get ETH denominated + * amount that is applicable to each supported token in the pool. + * + * It would be possible to support only 1 asset in the pool (and be exposed to all + * the assets while holding BPT tokens) and deposit/withdraw/checkBalance using only + * that asset. TBD: changes to other functions still required if we ever decide to + * go with such configuration. */ amount = (bptBalance.mulTruncate( IRateProvider(platformAddress).getRate() - ) / tokens.length); + ) / assetsMapped.length); /* If the pool asset is equal to (strategy )_asset it means that a rate * provider for that asset exists and that asset is not necessarily @@ -277,7 +313,6 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { view returns (address poolAsset, uint256 poolAmount) { - poolAmount = 0; if (asset == stETH) { poolAsset = wstETH; if (amount > 0) { @@ -340,18 +375,18 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { */ function unwrapPoolAsset(address asset, uint256 amount) internal - returns (uint256 wrappedAmount) + returns (uint256 unwrappedAmount) { if (asset == stETH) { - wrappedAmount = IWstETH(wstETH).unwrap(amount); + unwrappedAmount = IWstETH(wstETH).unwrap(amount); } else if (asset == frxETH) { - wrappedAmount = IERC4626(sfrxETH).withdraw( + unwrappedAmount = IERC4626(sfrxETH).withdraw( amount, address(this), address(this) ); } else { - wrappedAmount = amount; + unwrappedAmount = amount; } } From eb11498c376b65696c90981757221b076d6226aa Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Sun, 6 Aug 2023 22:54:19 +0200 Subject: [PATCH 29/67] bug fix --- .../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index d1e924ca47..0684615af0 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -94,7 +94,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address asset = _assets[i]; uint256 amount = _amounts[i]; - require(supportsAsset(asset), "Unsupported asset"); + require(assetToPToken[asset] != address(0), "Unsupported asset"); mappedAssets[i] = toPoolAsset(_assets[i]); if (amount > 0) { From a25a6617f0c715092f9857671942f0440031e5a9 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Mon, 7 Aug 2023 12:24:30 +1000 Subject: [PATCH 30/67] Generated latest Balancer strategy diagrams --- .../BalancerMetaPoolStrategyHierarchy.svg | 510 +++++++++--------- .../docs/BalancerMetaPoolStrategySquashed.svg | 54 +- .../docs/BalancerMetaPoolStrategyStorage.svg | 74 +-- 3 files changed, 325 insertions(+), 313 deletions(-) diff --git a/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg b/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg index 4ae82abd7d..81aab10525 100644 --- a/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg +++ b/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg @@ -4,326 +4,338 @@ - + UmlClassDiagram - + 7 - -Governable -../contracts/governance/Governable.sol + +Governable +../contracts/governance/Governable.sol 35 - -<<Interface>> -IOracle -../contracts/interfaces/IOracle.sol - - - -37 - -<<Interface>> -IRETH -../contracts/interfaces/IRETH.sol + +<<Interface>> +IOracle +../contracts/interfaces/IOracle.sol - + 42 - -<<Interface>> -IVault -../contracts/interfaces/IVault.sol + +<<Interface>> +IVault +../contracts/interfaces/IVault.sol - + -182 - -VaultStorage -../contracts/vault/VaultStorage.sol +184 + +VaultStorage +../contracts/vault/VaultStorage.sol - + -42->182 - - +42->184 + + - + 44 - -<<Interface>> -IWstETH -../contracts/interfaces/IWstETH.sol + +<<Interface>> +IWstETH +../contracts/interfaces/IWstETH.sol + + + +191 + +<<Interface>> +IBalancerVault +../contracts/interfaces/balancer/IBalancerVault.sol - + -189 - -<<Interface>> -IBalancerVault -../contracts/interfaces/balancer/IBalancerVault.sol +198 + +<<Interface>> +IMetaStablePool +../contracts/interfaces/balancer/IMetaStablePool.sol - + -197 - -<<Interface>> -IRateProvider -../contracts/interfaces/balancer/IRateProvider.sol +199 + +<<Interface>> +IRateProvider +../contracts/interfaces/balancer/IRateProvider.sol + + + +198->199 + + - + -150 - -<<Interface>> -IRewardStaking -../contracts/strategies/IRewardStaking.sol +152 + +<<Interface>> +IRewardStaking +../contracts/strategies/IRewardStaking.sol - + -229 - -BalancerMetaPoolStrategy -../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +231 + +BalancerMetaPoolStrategy +../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol - - -229->189 - - + + +231->191 + + + + + +231->198 + + + + + +231->199 + + - + -230 - -<<Abstract>> -BaseAuraStrategy -../contracts/strategies/balancer/BaseAuraStrategy.sol +232 + +<<Abstract>> +BaseAuraStrategy +../contracts/strategies/balancer/BaseAuraStrategy.sol - - -229->230 - - + + +231->232 + + - - -230->150 - - + + +232->152 + + - + -231 - -<<Abstract>> -BaseBalancerStrategy -../contracts/strategies/balancer/BaseBalancerStrategy.sol +233 + +<<Abstract>> +BaseBalancerStrategy +../contracts/strategies/balancer/BaseBalancerStrategy.sol - - -230->231 - - + + +232->233 + + - + -234 - -<<Interface>> -IERC4626 -../lib/openzeppelin/interfaces/IERC4626.sol - - - -230->234 - - - - - -231->35 - - +236 + +<<Interface>> +IERC4626 +../lib/openzeppelin/interfaces/IERC4626.sol - - -231->37 - - + + +232->236 + + - - -231->42 - - + + +233->35 + + - + -231->44 - - +233->42 + + - - -231->189 - - + + +233->44 + + - - -231->197 - - + + +233->191 + + - + + +233->199 + + + + -170 - -<<Abstract>> -InitializableAbstractStrategy -../contracts/utils/InitializableAbstractStrategy.sol +172 + +<<Abstract>> +InitializableAbstractStrategy +../contracts/utils/InitializableAbstractStrategy.sol - - -231->170 - - + + +233->172 + + - + -161 - -OUSD -../contracts/token/OUSD.sol +163 + +OUSD +../contracts/token/OUSD.sol - - -161->7 - - + + +163->7 + + - + -169 - -<<Abstract>> -Initializable -../contracts/utils/Initializable.sol +171 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol - - -161->169 - - + + +163->171 + + - + -172 - -<<Abstract>> -InitializableERC20Detailed -../contracts/utils/InitializableERC20Detailed.sol +174 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol - - -161->172 - - - - - -170->7 - - + + +163->174 + + - - -170->42 - - + + +172->7 + + - - -170->169 - - + + +172->42 + + - + -170->170 - - +172->171 + + - - -358 - -<<Interface>> -IERC20 -../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + +172->172 + + - - -170->358 - - + + +360 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - + -172->358 - - +172->360 + + - + -182->7 - - - - - -182->161 - - - - - -182->169 - - +174->360 + + - + -234->358 - - - - - -729 - -<<Interface>> -IERC20Metadata -../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol +184->7 + + - + -234->729 - - +184->163 + + - + + +184->171 + + + + -729->358 - - +236->360 + + + + + +731 + +<<Interface>> +IERC20Metadata +../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol + + + +236->731 + + + + + +731->360 + + diff --git a/contracts/docs/BalancerMetaPoolStrategySquashed.svg b/contracts/docs/BalancerMetaPoolStrategySquashed.svg index 741d7a018c..56a39bc216 100644 --- a/contracts/docs/BalancerMetaPoolStrategySquashed.svg +++ b/contracts/docs/BalancerMetaPoolStrategySquashed.svg @@ -4,18 +4,18 @@ - + UmlClassDiagram - - + + -229 - -BalancerMetaPoolStrategy -../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol - +231 + +BalancerMetaPoolStrategy +../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol + Private:   initialized: bool <<Initializable>>   initializing: bool <<Initializable>> @@ -28,8 +28,8 @@   _deprecated_rewardTokenAddress: address <<InitializableAbstractStrategy>>   _deprecated_rewardLiquidationThreshold: uint256 <<InitializableAbstractStrategy>>   _reserved: int256[98] <<InitializableAbstractStrategy>> -   __reserved: int256[50] <<BaseBalancerStrategy>> -   __reserved_2: int256[50] <<BaseAuraStrategy>> +   __reserved: int256[48] <<BaseBalancerStrategy>> +   __reserved_baseAuraStrategy: int256[50] <<BaseAuraStrategy>> Internal:   assetsMapped: address[] <<InitializableAbstractStrategy>> Public: @@ -50,7 +50,7 @@   maxWithdrawalSlippage: uint256 <<BaseBalancerStrategy>>   maxDepositSlippage: uint256 <<BaseBalancerStrategy>>   auraRewardPoolAddress: address <<BaseAuraStrategy>> - + Internal:    _governor(): (governorOut: address) <<Governable>>    _pendingGovernor(): (pendingGovernor: address) <<Governable>> @@ -71,18 +71,18 @@    toPoolAsset(asset: address, amount: uint256): (poolAsset: address, poolAmount: uint256) <<BaseBalancerStrategy>>    toPoolAsset(asset: address): address <<BaseBalancerStrategy>>    wrapPoolAsset(asset: address, amount: uint256): (wrappedAsset: address, wrappedAmount: uint256) <<BaseBalancerStrategy>> -    previewUnwrapPoolAsset(asset: address, assetAmount: uint256): (wrappedAmount: uint256) <<BaseBalancerStrategy>> -    unwrapPoolAsset(asset: address, amount: uint256): (wrappedAmount: uint256) <<BaseBalancerStrategy>> -    fromPoolAsset(poolAsset: address, poolAmount: uint256): (asset: address, amount: uint256) <<BaseBalancerStrategy>> -    fromPoolAsset(poolAsset: address): (asset: address) <<BaseBalancerStrategy>> -    _approveBase() <<BaseAuraStrategy>> +    unwrapPoolAsset(asset: address, amount: uint256): (unwrappedAmount: uint256) <<BaseBalancerStrategy>> +    fromPoolAsset(poolAsset: address, poolAmount: uint256): (asset: address, amount: uint256) <<BaseBalancerStrategy>> +    fromPoolAsset(poolAsset: address): (asset: address) <<BaseBalancerStrategy>> +    _approveBase() <<BaseAuraStrategy>> +    getRateProviderRate(_asset: address): uint256 <<BalancerMetaPoolStrategy>>    _deposit(_assets: address[], _amounts: uint256[]) <<BalancerMetaPoolStrategy>>    _withdraw(_recipient: address, _assets: address[], _amounts: uint256[]) <<BalancerMetaPoolStrategy>>    _approveAsset(_asset: address) <<BalancerMetaPoolStrategy>> External:    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>>    claimGovernance() <<Governable>> -    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<BaseAuraStrategy>> +    initialize(_rewardTokenAddresses: address[], _assets: address[], _pTokens: address[]) <<onlyGovernor, initializer>> <<BaseBalancerStrategy>>    collectRewardTokens() <<onlyHarvester, nonReentrant>> <<BaseAuraStrategy>>    setRewardTokenAddresses(_rewardTokenAddresses: address[]) <<onlyGovernor>> <<InitializableAbstractStrategy>>    getRewardTokenAddresses(): address[] <<InitializableAbstractStrategy>> @@ -90,17 +90,17 @@    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>>    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>>    safeApproveAllTokens() <<onlyGovernor, nonReentrant>> <<BalancerMetaPoolStrategy>> -    deposit(_asset: address, _amount: uint256) <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> -    depositAll() <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> -    withdraw(_recipient: address, _asset: address, _amount: uint256) <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> -    withdrawAll() <<whenNotInVaultContext, onlyVaultOrGovernor, nonReentrant>> <<BalancerMetaPoolStrategy>> -    checkBalance(_asset: address): (value: uint256) <<BaseBalancerStrategy>> +    deposit(_asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    depositAll() <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    withdraw(_recipient: address, _asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<BalancerMetaPoolStrategy>> +    checkBalance(_asset: address): (amount: uint256) <<whenNotInBalancerVaultContext>> <<BaseBalancerStrategy>>    supportsAsset(_asset: address): bool <<BaseBalancerStrategy>> -    checkBalance(): (value: uint256) <<BaseBalancerStrategy>> +    checkBalance(): (value: uint256) <<whenNotInBalancerVaultContext>> <<BaseBalancerStrategy>>    setMaxWithdrawalSlippage(_maxWithdrawalSlippage: uint256) <<onlyVaultOrGovernorOrStrategist>> <<BaseBalancerStrategy>>    setMaxDepositSlippage(_maxDepositSlippage: uint256) <<onlyVaultOrGovernorOrStrategist>> <<BaseBalancerStrategy>> -    deposit(_assets: address[], _amounts: uint256[]) <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> -    withdraw(_recipient: address, _assets: address[], _amounts: uint256[]) <<whenNotInVaultContext, onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    deposit(_assets: address[], _amounts: uint256[]) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    withdraw(_recipient: address, _assets: address[], _amounts: uint256[]) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> Public:    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>>    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> @@ -120,7 +120,7 @@    <<modifier>> onlyHarvester() <<InitializableAbstractStrategy>>    <<modifier>> onlyVaultOrGovernor() <<InitializableAbstractStrategy>>    <<modifier>> onlyVaultOrGovernorOrStrategist() <<InitializableAbstractStrategy>> -    <<modifier>> whenNotInVaultContext() <<BaseBalancerStrategy>> +    <<modifier>> whenNotInBalancerVaultContext() <<BaseBalancerStrategy>>    constructor() <<Governable>>    governor(): address <<Governable>>    isGovernor(): bool <<Governable>> diff --git a/contracts/docs/BalancerMetaPoolStrategyStorage.svg b/contracts/docs/BalancerMetaPoolStrategyStorage.svg index 28380694dc..8d76d6ec64 100644 --- a/contracts/docs/BalancerMetaPoolStrategyStorage.svg +++ b/contracts/docs/BalancerMetaPoolStrategyStorage.svg @@ -43,9 +43,9 @@ 158 -159-208 +159-206 -209-258 +207-256 type: <inherited contract>.variable (bytes) @@ -87,9 +87,9 @@ uint256: BaseBalancerStrategy.maxDepositSlippage (32) -int256[50]: BaseBalancerStrategy.__reserved (1600) +int256[48]: BaseBalancerStrategy.__reserved (1536) -int256[50]: BaseAuraStrategy.__reserved_2 (1600) +int256[50]: BaseAuraStrategy.__reserved_baseAuraStrategy (1600) @@ -213,7 +213,7 @@ 5 -int256[50]: __reserved <<Array>> +int256[48]: __reserved <<Array>> slot @@ -221,11 +221,11 @@ 160 -161-206 +161-204 -207 +205 -208 +206 type: variable (bytes) @@ -233,7 +233,7 @@ int256 (32) ----- (1472) +---- (1408) int256 (32) @@ -248,38 +248,38 @@ 6 - -int256[50]: __reserved_2 <<Array>> - -slot - -209 - -210 - -211-256 - -257 - -258 - -type: variable (bytes) - -int256 (32) - -int256 (32) - ----- (1472) - -int256 (32) - -int256 (32) + +int256[50]: __reserved_baseAuraStrategy <<Array>> + +slot + +207 + +208 + +209-254 + +255 + +256 + +type: variable (bytes) + +int256 (32) + +int256 (32) + +---- (1472) + +int256 (32) + +int256 (32) 7:38->6 - - + + From b9dd48076ea60b01e5af55b399460f009992ed1d Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 7 Aug 2023 22:56:55 +0200 Subject: [PATCH 31/67] re-deploy BPT tokens sitting in the strategy --- .../strategies/balancer/BalancerMetaPoolStrategy.sol | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 0684615af0..49bb0e8d40 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -299,7 +299,15 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { request ); - // STEP 5 - Unswap balancer pool assets to vault collateral assets and sent to the vault. + // STEP 5 - Re-deposit any left over BPT tokens back into Aura + /* When concluding how much of BPT we need to withdraw from Aura we rely on Oracle prices + * and those can be stale (most ETH based have 24 hour heartbeat & 2% price change trigger) + * After exiting the pool strategy could have left over BPT tokens that are not earning + * boosted yield. We re-deploy those back in. + */ + _lpDepositAll(); + + // STEP 6 - Unswap balancer pool assets to vault collateral assets and sent to the vault. // For each of the specified assets for (uint256 i = 0; i < _assets.length; ++i) { From 3767bb2e8941252af443ad8e1e09a0c8b71d64d9 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 10 Aug 2023 09:35:25 +0200 Subject: [PATCH 32/67] fix re-entrancy test --- contracts/test/strategies/balancerPoolReentrancy.fork-test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js index 75f24758b3..2d4f0abd69 100644 --- a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js +++ b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js @@ -60,8 +60,10 @@ forkOnlyDescribe( await impersonateAndFundContract(cEvilContract.address), "100000" ); + // ... and rETH const rethHolder = await findBestMainnetTokenHolder(reth, hre); + await impersonateAndFundContract(await rethHolder.getAddress()); await reth .connect(rethHolder) .transfer(cEvilContract.address, utils.parseEther("1000")); From c69369e3faa9fc304487ce7115f1b75fbbb8d87c Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 17 Aug 2023 12:08:58 +0200 Subject: [PATCH 33/67] fixture fix --- contracts/test/_fixture.js | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 2c0b654860..9e9d83f762 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -244,7 +244,6 @@ const defaultFixture = deployments.createFixture(async () => { frxETH = await ethers.getContractAt(erc20Abi, addresses.mainnet.frxETH); sfrxETH = await ethers.getContractAt(sfrxETHAbi, addresses.mainnet.sfrxETH); sDAI = await ethers.getContractAt(sdaiAbi, addresses.mainnet.sDAI); - reth = await ethers.getContractAt(erc20Abi, addresses.mainnet.rETH); morpho = await ethers.getContractAt(morphoAbi, addresses.mainnet.Morpho); morphoLens = await ethers.getContractAt( morphoLensAbi, From 8a26a4edb2ba498ed618a0588a02a1623ed92f1d Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 17 Aug 2023 13:30:48 +0200 Subject: [PATCH 34/67] bug fix --- contracts/test/_fixture.js | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 9e9d83f762..2dd2bf9850 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -243,6 +243,7 @@ const defaultFixture = deployments.createFixture(async () => { reth = await ethers.getContractAt("IRETH", addresses.mainnet.rETH); frxETH = await ethers.getContractAt(erc20Abi, addresses.mainnet.frxETH); sfrxETH = await ethers.getContractAt(sfrxETHAbi, addresses.mainnet.sfrxETH); + stETH = await ethers.getContractAt(erc20Abi, addresses.mainnet.stETH); sDAI = await ethers.getContractAt(sdaiAbi, addresses.mainnet.sDAI); morpho = await ethers.getContractAt(morphoAbi, addresses.mainnet.Morpho); morphoLens = await ethers.getContractAt( From afb2d67ec264917047f0bc7200d9a44e9d89ff83 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 17 Aug 2023 13:31:12 +0200 Subject: [PATCH 35/67] prettier --- .../strategies/balancerMetaStablePool.fork-test.js | 8 +++++--- .../strategies/balancerPoolReentrancy.fork-test.js | 11 +++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 95fd6d5f3b..5e0de93570 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -15,13 +15,15 @@ const { const log = require("../../utils/logger")("test:fork:strategy:balancer"); const loadBalancerREthFixtureDefault = createFixtureLoader( - balancerREthFixture, { + balancerREthFixture, + { defaultStrategy: true, } ); const loadBalancerREthFixtureNotDefault = createFixtureLoader( - balancerREthFixture, { + balancerREthFixture, + { defaultStrategy: false, } ); @@ -563,7 +565,7 @@ forkOnlyDescribe( let fixture; beforeEach(async () => { - fixture = await loadBalancerWstEthFixture(); + fixture = await loadBalancerWstEthFixture(); const { balancerWstEthStrategy, oethVault, strategist, stETH, weth } = fixture; diff --git a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js index 2d4f0abd69..5bec3b2452 100644 --- a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js +++ b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js @@ -21,18 +21,17 @@ forkOnlyDescribe( this.retries(isCI ? 3 : 0); let fixture; - const loadFixture = createFixtureLoader( - balancerREthFixture, { - defaultStrategy: true, - } - ); + const loadFixture = createFixtureLoader(balancerREthFixture, { + defaultStrategy: true, + }); beforeEach(async () => { fixture = await loadFixture(); }); it.only("Should not allow read-only reentrancy", async () => { - const { weth, reth, oethVault, rEthBPT, balancerREthPID, daniel } = fixture; + const { weth, reth, oethVault, rEthBPT, balancerREthPID, daniel } = + fixture; // Deploy the attacking contract const dEvilContract = await deployWithConfirmation( From 34608a740828308bc7fec763afed771de0afc48a Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 28 Aug 2023 14:04:17 +0200 Subject: [PATCH 36/67] L02 improve naming (#1783) * improve naming * one more rename * buf fix --- .../balancer/BalancerMetaPoolStrategy.sol | 215 +++++++++++------- 1 file changed, 127 insertions(+), 88 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 49bb0e8d40..873795f0e3 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -30,35 +30,34 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { /** * @notice Deposits an `_amount` of vault collateral assets * from the this strategy contract to the Balancer pool. - * @param _asset Address of the Vault collateral asset - * @param _amount The amount of Vault collateral assets to deposit + * @param _strategyAsset Address of the Vault collateral asset + * @param _strategyAmount The amount of Vault collateral assets to deposit */ - function deposit(address _asset, uint256 _amount) + function deposit(address _strategyAsset, uint256 _strategyAmount) external override onlyVault nonReentrant { - address[] memory assets = new address[](1); - uint256[] memory amounts = new uint256[](1); - assets[0] = _asset; - amounts[0] = _amount; + address[] memory strategyAssets = new address[](1); + uint256[] memory strategyAmounts = new uint256[](1); + strategyAssets[0] = _strategyAsset; + strategyAmounts[0] = _strategyAmount; - _deposit(assets, amounts); + _deposit(strategyAssets, strategyAmounts); } /** * @notice Deposits specified vault collateral assets * from the this strategy contract to the Balancer pool. - * @param _assets Address of the Vault collateral assets - * @param _amounts The amount of each asset to deposit + * @param _strategyAssets Address of the Vault collateral assets + * @param _strategyAmounts The amount of each asset to deposit */ - function deposit(address[] memory _assets, uint256[] memory _amounts) - external - onlyVault - nonReentrant - { - _deposit(_assets, _amounts); + function deposit( + address[] memory _strategyAssets, + uint256[] memory _strategyAmounts + ) external onlyVault nonReentrant { + _deposit(_strategyAssets, _strategyAmounts); } /** @@ -66,42 +65,56 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ function depositAll() external override onlyVault nonReentrant { uint256 assetsLength = assetsMapped.length; - address[] memory assets = new address[](assetsLength); - uint256[] memory amounts = new uint256[](assetsLength); + address[] memory strategyAssets = new address[](assetsLength); + uint256[] memory strategyAmounts = new uint256[](assetsLength); // For each vault collateral asset for (uint256 i = 0; i < assetsLength; ++i) { - assets[i] = assetsMapped[i]; + strategyAssets[i] = assetsMapped[i]; // Get the asset balance in this strategy contract - amounts[i] = IERC20(assets[i]).balanceOf(address(this)); + strategyAmounts[i] = IERC20(strategyAssets[i]).balanceOf(address(this)); } - _deposit(assets, amounts); + _deposit(strategyAssets, strategyAmounts); } - function _deposit(address[] memory _assets, uint256[] memory _amounts) - internal - { - require(_assets.length == _amounts.length, "Array length missmatch"); + function _deposit( + address[] memory _strategyAssets, + uint256[] memory _strategyAmounts + ) internal { + require( + _strategyAssets.length == _strategyAmounts.length, + "Array length missmatch" + ); (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( balancerPoolId ); - uint256[] memory mappedAmounts = new uint256[](tokens.length); - address[] memory mappedAssets = new address[](tokens.length); + uint256[] memory strategyAssetAmountsToPoolAssetAmounts = new uint256[]( + tokens.length + ); + address[] memory strategyAssetsToPoolAssets = new address[]( + tokens.length + ); - for (uint256 i = 0; i < _assets.length; ++i) { - address asset = _assets[i]; - uint256 amount = _amounts[i]; + for (uint256 i = 0; i < _strategyAssets.length; ++i) { + address strategyAsset = _strategyAssets[i]; + uint256 strategyAmount = _strategyAmounts[i]; - require(assetToPToken[asset] != address(0), "Unsupported asset"); - mappedAssets[i] = toPoolAsset(_assets[i]); + require( + assetToPToken[strategyAsset] != address(0), + "Unsupported asset" + ); + strategyAssetsToPoolAssets[i] = toPoolAsset(_strategyAssets[i]); - if (amount > 0) { - emit Deposit(asset, platformAddress, amount); + if (strategyAmount > 0) { + emit Deposit(strategyAsset, platformAddress, strategyAmount); // wrap rebasing assets like stETH and frxETH to wstETH and sfrxETH - (, mappedAmounts[i]) = wrapPoolAsset(asset, amount); + (, strategyAssetAmountsToPoolAssetAmounts[i]) = wrapPoolAsset( + strategyAsset, + strategyAmount + ); } } @@ -112,15 +125,15 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { poolAssets[i] = address(tokens[i]); // For each of the mapped assets - for (uint256 j = 0; j < mappedAssets.length; ++j) { + for (uint256 j = 0; j < strategyAssetsToPoolAssets.length; ++j) { // If the pool asset is the same as the mapped asset - if (poolAssets[i] == mappedAssets[j]) { - amountsIn[i] = mappedAmounts[j]; + if (poolAssets[i] == strategyAssetsToPoolAssets[j]) { + amountsIn[i] = strategyAssetAmountsToPoolAssetAmounts[j]; } } } - uint256 minBPT = getBPTExpected(_assets, _amounts); + uint256 minBPT = getBPTExpected(_strategyAssets, _strategyAmounts); uint256 minBPTwSlippage = minBPT.mulTruncate(1e18 - maxDepositSlippage); /* EXACT_TOKENS_IN_FOR_BPT_OUT: @@ -154,53 +167,59 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { /** * @notice Withdraw a Vault collateral asset from the Balancer pool. * @param _recipient Address to receive the Vault collateral assets. Typically is the Vault. - * @param _asset Address of the Vault collateral asset - * @param _amount The amount of Vault collateral assets to withdraw + * @param _strategyAsset Address of the Vault collateral asset + * @param _strategyAmount The amount of Vault collateral assets to withdraw */ function withdraw( address _recipient, - address _asset, - uint256 _amount + address _strategyAsset, + uint256 _strategyAmount ) external override onlyVault nonReentrant { - address[] memory assets = new address[](1); - uint256[] memory amounts = new uint256[](1); - assets[0] = _asset; - amounts[0] = _amount; + address[] memory strategyAssets = new address[](1); + uint256[] memory strategyAmounts = new uint256[](1); + strategyAssets[0] = _strategyAsset; + strategyAmounts[0] = _strategyAmount; - _withdraw(_recipient, assets, amounts); + _withdraw(_recipient, strategyAssets, strategyAmounts); } /** * @notice Withdraw multiple Vault collateral asset from the Balancer pool. * @param _recipient Address to receive the Vault collateral assets. Typically is the Vault. - * @param _assets Addresses of the Vault collateral assets - * @param _amounts The amounts of Vault collateral assets to withdraw + * @param _strategyAssets Addresses of the Vault collateral assets + * @param _strategyAmounts The amounts of Vault collateral assets to withdraw */ function withdraw( address _recipient, - address[] memory _assets, - uint256[] memory _amounts + address[] memory _strategyAssets, + uint256[] memory _strategyAmounts ) external onlyVault nonReentrant { - _withdraw(_recipient, _assets, _amounts); + _withdraw(_recipient, _strategyAssets, _strategyAmounts); } /** * @dev Withdraw multiple Vault collateral asset from the Balancer pool. * @param _recipient Address to receive the Vault collateral assets. Typically is the Vault. - * @param _assets Addresses of the Vault collateral assets - * @param _amounts The amounts of Vault collateral assets to withdraw + * @param _strategyAssets Addresses of the Vault collateral assets + * @param _strategyAmounts The amounts of Vault collateral assets to withdraw */ function _withdraw( address _recipient, - address[] memory _assets, - uint256[] memory _amounts + address[] memory _strategyAssets, + uint256[] memory _strategyAmounts ) internal { - require(_assets.length == _amounts.length, "Invalid input arrays"); + require( + _strategyAssets.length == _strategyAmounts.length, + "Invalid input arrays" + ); // STEP 1 - Calculate the max about of Balancer Pool Tokens (BPT) to withdraw // Estimate the required amount of Balancer Pool Tokens (BPT) for the assets - uint256 maxBPTtoWithdraw = getBPTExpected(_assets, _amounts); + uint256 maxBPTtoWithdraw = getBPTExpected( + _strategyAssets, + _strategyAmounts + ); // Increase BPTs by the max allowed slippage // Any excess BPTs will be left in this strategy contract maxBPTtoWithdraw = maxBPTtoWithdraw.mulTruncate( @@ -221,28 +240,32 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { balancerPoolId ); // Calculate the balancer pool assets and amounts to withdraw - uint256[] memory poolAmountsOut = new uint256[](tokens.length); + uint256[] memory poolAssetsAmountsOut = new uint256[](tokens.length); address[] memory poolAssets = new address[](tokens.length); // Is the wrapped asset amount indexed by the assets array, not the order of the Balancer pool tokens // eg wstETH and sfrxETH amounts, not the stETH and frxETH amounts - uint256[] memory wrappedAssetAmounts = new uint256[](_assets.length); + uint256[] memory strategyAssetsToPoolAssetsAmounts = new uint256[]( + _strategyAssets.length + ); // For each of the Balancer pool assets for (uint256 i = 0; i < tokens.length; ++i) { poolAssets[i] = address(tokens[i]); // for each of the vault assets - for (uint256 j = 0; j < _assets.length; ++j) { - // Convert the Balancer pool asset back to a vault collateral asset - address vaultAsset = fromPoolAsset(poolAssets[i]); + for (uint256 j = 0; j < _strategyAssets.length; ++j) { + // Convert the Balancer pool asset back to a strategy asset + address strategyAsset = fromPoolAsset(poolAssets[i]); // If the vault asset equals the vault asset mapped from the Balancer pool asset - if (_assets[j] == vaultAsset) { - (, poolAmountsOut[i]) = toPoolAsset( - vaultAsset, - _amounts[j] + if (_strategyAssets[j] == strategyAsset) { + (, poolAssetsAmountsOut[i]) = toPoolAsset( + strategyAsset, + _strategyAmounts[j] ); - wrappedAssetAmounts[j] = poolAmountsOut[i]; + strategyAssetsToPoolAssetsAmounts[j] = poolAssetsAmountsOut[ + i + ]; /* Because of the potential Balancer rounding error mentioned below * the contract might receive 1-2 WEI smaller amount than required @@ -253,8 +276,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { * For that reason we `overshoot` the required tokens expected to * circumvent the error */ - if (poolAmountsOut[i] > 0) { - poolAmountsOut[i] += 2; + if (poolAssetsAmountsOut[i] > 0) { + poolAssetsAmountsOut[i] += 2; } } } @@ -271,7 +294,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ bytes memory userData = abi.encode( IBalancerVault.WeightedPoolExitKind.BPT_IN_FOR_EXACT_TOKENS_OUT, - poolAmountsOut, + poolAssetsAmountsOut, maxBPTtoWithdraw ); @@ -310,21 +333,27 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { // STEP 6 - Unswap balancer pool assets to vault collateral assets and sent to the vault. // For each of the specified assets - for (uint256 i = 0; i < _assets.length; ++i) { + for (uint256 i = 0; i < _strategyAssets.length; ++i) { // Unwrap assets like wstETH and sfrxETH to rebasing assets stETH and frxETH - uint256 assetAmount = 0; - if (wrappedAssetAmounts[i] > 0) { - assetAmount = unwrapPoolAsset( - _assets[i], - wrappedAssetAmounts[i] + if (strategyAssetsToPoolAssetsAmounts[i] > 0) { + unwrapPoolAsset( + _strategyAssets[i], + strategyAssetsToPoolAssetsAmounts[i] ); } // Transfer the vault collateral assets to the recipient, which is typically the vault - if (_amounts[i] > 0) { - IERC20(_assets[i]).safeTransfer(_recipient, _amounts[i]); + if (_strategyAmounts[i] > 0) { + IERC20(_strategyAssets[i]).safeTransfer( + _recipient, + _strategyAmounts[i] + ); - emit Withdrawal(_assets[i], platformAddress, _amounts[i]); + emit Withdrawal( + _strategyAssets[i], + platformAddress, + _strategyAmounts[i] + ); } } } @@ -396,23 +425,33 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { // For each of the Balancer pool assets for (uint256 i = 0; i < tokens.length; ++i) { address poolAsset = address(tokens[i]); - // Convert the balancer pool asset to the vault collateral asset - address asset = fromPoolAsset(poolAsset); + // Convert the balancer pool asset to the strategy asset + address strategyAsset = fromPoolAsset(poolAsset); // Get the balancer pool assets withdraw from the pool plus any that were already in this strategy contract uint256 poolAssetAmount = IERC20(poolAsset).balanceOf( address(this) ); // Unwrap assets like wstETH and sfrxETH to rebasing assets stETH and frxETH - uint256 assetAmount = 0; + uint256 unwrappedAmount = 0; if (poolAssetAmount > 0) { - assetAmount = unwrapPoolAsset(asset, poolAssetAmount); + unwrappedAmount = unwrapPoolAsset( + strategyAsset, + poolAssetAmount + ); } // Transfer the vault collateral assets to the vault - if (assetAmount > 0) { - IERC20(asset).safeTransfer(vaultAddress, assetAmount); - emit Withdrawal(asset, platformAddress, assetAmount); + if (unwrappedAmount > 0) { + IERC20(strategyAsset).safeTransfer( + vaultAddress, + unwrappedAmount + ); + emit Withdrawal( + strategyAsset, + platformAddress, + unwrappedAmount + ); } } } From a32344769e06b922b22f7ec0ffb83653eb551e17 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 28 Aug 2023 14:20:15 +0200 Subject: [PATCH 37/67] do a check that supported assets are being withdrawn (#1784) --- .../strategies/balancer/BalancerMetaPoolStrategy.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 873795f0e3..1a6ab905aa 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -213,6 +213,10 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { "Invalid input arrays" ); + for (uint256 i = 0; i < _assets.length; ++i) { + require(assetToPToken[_assets] != address(0), "Unsupported asset"); + } + // STEP 1 - Calculate the max about of Balancer Pool Tokens (BPT) to withdraw // Estimate the required amount of Balancer Pool Tokens (BPT) for the assets From 7d8c3faed02b08d1349bd06d628e9d5aee9c3fd9 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 28 Aug 2023 14:26:39 +0200 Subject: [PATCH 38/67] set uint256 max instead of magic number (#1782) --- .../strategies/balancer/BalancerMetaPoolStrategy.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 1a6ab905aa..d7240a4287 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -487,10 +487,10 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address poolAsset = toPoolAsset(_asset); if (_asset == stETH) { // slither-disable-next-line unused-return - IERC20(stETH).approve(wstETH, 1e50); + IERC20(stETH).approve(wstETH, type(uint256).max); } else if (_asset == frxETH) { // slither-disable-next-line unused-return - IERC20(frxETH).approve(sfrxETH, 1e50); + IERC20(frxETH).approve(sfrxETH, type(uint256).max); } _approveAsset(poolAsset); } From d4eef49f94009b241da1034f2b2e44d9d2bc630e Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 28 Aug 2023 14:27:48 +0200 Subject: [PATCH 39/67] remove unused files (#1785) --- contracts/contracts/interfaces/IERC20Details.sol | 4 ---- .../contracts/strategies/balancer/BaseBalancerStrategy.sol | 1 - 2 files changed, 5 deletions(-) delete mode 100644 contracts/contracts/interfaces/IERC20Details.sol diff --git a/contracts/contracts/interfaces/IERC20Details.sol b/contracts/contracts/interfaces/IERC20Details.sol deleted file mode 100644 index 117f5b2e5b..0000000000 --- a/contracts/contracts/interfaces/IERC20Details.sol +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 1e8b620f8f..df4b0c3377 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -12,7 +12,6 @@ import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { VaultReentrancyLib } from "./VaultReentrancyLib.sol"; import { IOracle } from "../../interfaces/IOracle.sol"; import { IVault } from "../../interfaces/IVault.sol"; -import { IRETH } from "../../interfaces/IRETH.sol"; import { IWstETH } from "../../interfaces/IWstETH.sol"; import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; import { StableMath } from "../../utils/StableMath.sol"; From 4d36852ea0d8d1315ce113a3ec68a76b499edd33 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 01:28:47 +0200 Subject: [PATCH 40/67] fix renaming bug --- .../strategies/balancer/BalancerMetaPoolStrategy.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index d7240a4287..99eaab673d 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -213,8 +213,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { "Invalid input arrays" ); - for (uint256 i = 0; i < _assets.length; ++i) { - require(assetToPToken[_assets] != address(0), "Unsupported asset"); + for (uint256 i = 0; i < _strategyAssets.length; ++i) { + require(assetToPToken[_strategyAssets[i]] != address(0), "Unsupported asset"); } // STEP 1 - Calculate the max about of Balancer Pool Tokens (BPT) to withdraw From d206ce4f9bd133d6167daff392f3bce042ef04a7 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 12:18:16 +0200 Subject: [PATCH 41/67] correct safe approve all tokens and adjust the documentation (#1776) --- .../balancer/BalancerMetaPoolStrategy.sol | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 99eaab673d..2d9bcc7908 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -461,11 +461,15 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { } /** - * @notice Approves the Balancer pool to transfer all supported - * assets from this strategy. - * Also approve any suppered assets that are wrapped in the Balancer pool - * like stETH and frxETH, to be transferred from this strategy to their - * respective wrapper contracts. eg wstETH and sfrxETH. + * @notice Approves the Balancer Vault to transfer poolAsset counterparts + * of all of the supported assets from this strategy. E.g. stETH is a supported + * strategy and Balancer Vault gets unlimited approval to transfer wstETH. + * + * If Balancer pool uses a wrapped version of a supported asset then also approve + * unlimited usage of an asset to the contract responsible for wrapping. + * + * Approve unlimited spending by Balancer Vault and Aura reward pool of the + * pool BPT tokens. * * Is only executable by the Governor. */ @@ -477,7 +481,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { { uint256 assetCount = assetsMapped.length; for (uint256 i = 0; i < assetCount; ++i) { - _approveAsset(assetsMapped[i]); + _abstractSetPToken(assetsMapped[i], platformAddress); } _approveBase(); } From b127355ec81fe421a4f51c7055f651ac5f333b6a Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 12:24:29 +0200 Subject: [PATCH 42/67] prettier --- .../strategies/balancer/BalancerMetaPoolStrategy.sol | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 2d9bcc7908..835625637f 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -72,7 +72,9 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { for (uint256 i = 0; i < assetsLength; ++i) { strategyAssets[i] = assetsMapped[i]; // Get the asset balance in this strategy contract - strategyAmounts[i] = IERC20(strategyAssets[i]).balanceOf(address(this)); + strategyAmounts[i] = IERC20(strategyAssets[i]).balanceOf( + address(this) + ); } _deposit(strategyAssets, strategyAmounts); } @@ -214,7 +216,10 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { ); for (uint256 i = 0; i < _strategyAssets.length; ++i) { - require(assetToPToken[_strategyAssets[i]] != address(0), "Unsupported asset"); + require( + assetToPToken[_strategyAssets[i]] != address(0), + "Unsupported asset" + ); } // STEP 1 - Calculate the max about of Balancer Pool Tokens (BPT) to withdraw From 6ad405cae7c3884516e8408363def61b2ccac2bb Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 21:58:18 +0200 Subject: [PATCH 43/67] M04 - minBptFunction robustness (#1795) * change bptExpected to ignore Oracle prices and assume assets are always pegged. (Vault value checker shall be used to mitigate issues with said assumption) * fix all the tests * add test for pool manipulation * prettier & lint * minor change * add withdrawal test * update documentation * pick string error length that is smaller than 32 characters * prettier * correct comment * better comments * prettier --- brownie/abi/balancer_strat.json | 2 +- .../balancer/BalancerMetaPoolStrategy.sol | 100 +++--- .../balancer/BaseBalancerStrategy.sol | 132 ++++---- contracts/test/_fixture.js | 81 +++++ .../balancerMetaStablePool.fork-test.js | 302 ++++++++++++++++-- .../balancerPoolReentrancy.fork-test.js | 2 +- contracts/utils/temporaryFork.js | 30 ++ 7 files changed, 503 insertions(+), 146 deletions(-) create mode 100644 contracts/utils/temporaryFork.js diff --git a/brownie/abi/balancer_strat.json b/brownie/abi/balancer_strat.json index 28e89124b0..85dfc29434 100644 --- a/brownie/abi/balancer_strat.json +++ b/brownie/abi/balancer_strat.json @@ -1 +1 @@ -[{"inputs": [{"components": [{"internalType": "address","name": "platformAddress","type": "address"},{"internalType": "address","name": "vaultAddress","type": "address"}],"internalType": "struct InitializableAbstractStrategy.BaseStrategyConfig","name": "_stratConfig","type": "tuple"},{"components": [{"internalType": "address","name": "rEthAddress","type": "address"},{"internalType": "address","name": "stEthAddress","type": "address"},{"internalType": "address","name": "wstEthAddress","type": "address"},{"internalType": "address","name": "frxEthAddress","type": "address"},{"internalType": "address","name": "sfrxEthAddress","type": "address"},{"internalType": "address","name": "balancerVaultAddress","type": "address"},{"internalType": "bytes32","name": "balancerPoolId","type": "bytes32"}],"internalType": "struct BaseBalancerStrategy.BaseBalancerConfig","name": "_balancerConfig","type": "tuple"},{"internalType": "address","name": "_auraRewardPoolAddress","type": "address"}],"stateMutability": "nonpayable","type": "constructor"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "Deposit","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "previousGovernor","type": "address"},{"indexed": true,"internalType": "address","name": "newGovernor","type": "address"}],"name": "GovernorshipTransferred","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address","name": "_oldHarvesterAddress","type": "address"},{"indexed": false,"internalType": "address","name": "_newHarvesterAddress","type": "address"}],"name": "HarvesterAddressesUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "_prevMaxSlippagePercentage","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "_newMaxSlippagePercentage","type": "uint256"}],"name": "MaxDepositSlippageUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "_prevMaxSlippagePercentage","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "_newMaxSlippagePercentage","type": "uint256"}],"name": "MaxWithdrawalSlippageUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"}],"name": "PTokenAdded","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"}],"name": "PTokenRemoved","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "previousGovernor","type": "address"},{"indexed": true,"internalType": "address","name": "newGovernor","type": "address"}],"name": "PendingGovernorshipTransfer","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address[]","name": "_oldAddresses","type": "address[]"},{"indexed": false,"internalType": "address[]","name": "_newAddresses","type": "address[]"}],"name": "RewardTokenAddressesUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address","name": "recipient","type": "address"},{"indexed": false,"internalType": "address","name": "rewardToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "RewardTokenCollected","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "Withdrawal","type": "event"},{"inputs": [{"internalType": "address","name": "","type": "address"}],"name": "assetToPToken","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "auraRewardPoolAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "balancerPoolId","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "balancerVault","outputs": [{"internalType": "contract IBalancerVault","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance2","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance3","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "checkBalance","outputs": [{"internalType": "uint256","name": "value","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "claimGovernance","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "collectRewardTokens","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "deposit","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "uint256[]","name": "_amounts","type": "uint256[]"}],"name": "deposit","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "depositAll","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "frxETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "getRewardTokenAddresses","outputs": [{"internalType": "address[]","name": "","type": "address[]"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "governor","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "harvesterAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address[]","name": "_rewardTokenAddresses","type": "address[]"},{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "address[]","name": "_pTokens","type": "address[]"}],"name": "initialize","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "isGovernor","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxDepositSlippage","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxWithdrawalSlippage","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "platformAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "rETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "_assetIndex","type": "uint256"}],"name": "removePToken","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "","type": "uint256"}],"name": "rewardTokenAddresses","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "safeApproveAllTokens","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_harvesterAddress","type": "address"}],"name": "setHarvesterAddress","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "_maxDepositSlippage","type": "uint256"}],"name": "setMaxDepositSlippage","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "_maxWithdrawalSlippage","type": "uint256"}],"name": "setMaxWithdrawalSlippage","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "address","name": "_pToken","type": "address"}],"name": "setPTokenAddress","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address[]","name": "_rewardTokenAddresses","type": "address[]"}],"name": "setRewardTokenAddresses","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "sfrxETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "stETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "supportsAsset","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_newGovernor","type": "address"}],"name": "transferGovernance","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "transferToken","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "vaultAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_recipient","type": "address"},{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "withdraw","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_recipient","type": "address"},{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "uint256[]","name": "_amounts","type": "uint256[]"}],"name": "withdraw","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "withdrawAll","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "wstETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"}] \ No newline at end of file +[{"inputs": [{"components": [{"internalType": "address","name": "platformAddress","type": "address"},{"internalType": "address","name": "vaultAddress","type": "address"}],"internalType": "struct InitializableAbstractStrategy.BaseStrategyConfig","name": "_stratConfig","type": "tuple"},{"components": [{"internalType": "address","name": "rEthAddress","type": "address"},{"internalType": "address","name": "stEthAddress","type": "address"},{"internalType": "address","name": "wstEthAddress","type": "address"},{"internalType": "address","name": "frxEthAddress","type": "address"},{"internalType": "address","name": "sfrxEthAddress","type": "address"},{"internalType": "address","name": "balancerVaultAddress","type": "address"},{"internalType": "bytes32","name": "balancerPoolId","type": "bytes32"}],"internalType": "struct BaseBalancerStrategy.BaseBalancerConfig","name": "_balancerConfig","type": "tuple"},{"internalType": "address","name": "_auraRewardPoolAddress","type": "address"}],"stateMutability": "nonpayable","type": "constructor"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "Deposit","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "previousGovernor","type": "address"},{"indexed": true,"internalType": "address","name": "newGovernor","type": "address"}],"name": "GovernorshipTransferred","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address","name": "_oldHarvesterAddress","type": "address"},{"indexed": false,"internalType": "address","name": "_newHarvesterAddress","type": "address"}],"name": "HarvesterAddressesUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "_prevMaxSlippagePercentage","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "_newMaxSlippagePercentage","type": "uint256"}],"name": "MaxDepositDeviationUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "_prevMaxSlippagePercentage","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "_newMaxSlippagePercentage","type": "uint256"}],"name": "MaxWithdrawalDeviationUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"}],"name": "PTokenAdded","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"}],"name": "PTokenRemoved","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "previousGovernor","type": "address"},{"indexed": true,"internalType": "address","name": "newGovernor","type": "address"}],"name": "PendingGovernorshipTransfer","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address[]","name": "_oldAddresses","type": "address[]"},{"indexed": false,"internalType": "address[]","name": "_newAddresses","type": "address[]"}],"name": "RewardTokenAddressesUpdated","type": "event"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "address","name": "recipient","type": "address"},{"indexed": false,"internalType": "address","name": "rewardToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "amount","type": "uint256"}],"name": "RewardTokenCollected","type": "event"},{"anonymous": false,"inputs": [{"indexed": true,"internalType": "address","name": "_asset","type": "address"},{"indexed": false,"internalType": "address","name": "_pToken","type": "address"},{"indexed": false,"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "Withdrawal","type": "event"},{"inputs": [{"internalType": "address","name": "","type": "address"}],"name": "assetToPToken","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "auraRewardPoolAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "balancerPoolId","outputs": [{"internalType": "bytes32","name": "","type": "bytes32"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "balancerVault","outputs": [{"internalType": "contract IBalancerVault","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance2","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "checkBalance3","outputs": [{"internalType": "uint256","name": "amount","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "checkBalance","outputs": [{"internalType": "uint256","name": "value","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "claimGovernance","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "collectRewardTokens","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "deposit","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "uint256[]","name": "_amounts","type": "uint256[]"}],"name": "deposit","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "depositAll","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "frxETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "getRewardTokenAddresses","outputs": [{"internalType": "address[]","name": "","type": "address[]"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "governor","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "harvesterAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address[]","name": "_rewardTokenAddresses","type": "address[]"},{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "address[]","name": "_pTokens","type": "address[]"}],"name": "initialize","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "isGovernor","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxDepositDeviation","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "maxWithdrawalDeviation","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "platformAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "rETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "_assetIndex","type": "uint256"}],"name": "removePToken","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "","type": "uint256"}],"name": "rewardTokenAddresses","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "safeApproveAllTokens","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_harvesterAddress","type": "address"}],"name": "setHarvesterAddress","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "_maxDepositDeviation","type": "uint256"}],"name": "setMaxDepositDeviation","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "uint256","name": "_maxWithdrawalDeviation","type": "uint256"}],"name": "setMaxWithdrawalDeviation","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "address","name": "_pToken","type": "address"}],"name": "setPTokenAddress","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address[]","name": "_rewardTokenAddresses","type": "address[]"}],"name": "setRewardTokenAddresses","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "sfrxETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "stETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"}],"name": "supportsAsset","outputs": [{"internalType": "bool","name": "","type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_newGovernor","type": "address"}],"name": "transferGovernance","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "transferToken","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "vaultAddress","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "address","name": "_recipient","type": "address"},{"internalType": "address","name": "_asset","type": "address"},{"internalType": "uint256","name": "_amount","type": "uint256"}],"name": "withdraw","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "address","name": "_recipient","type": "address"},{"internalType": "address[]","name": "_assets","type": "address[]"},{"internalType": "uint256[]","name": "_amounts","type": "uint256[]"}],"name": "withdraw","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "withdrawAll","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"name": "wstETH","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"}] \ No newline at end of file diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 835625637f..d25b2734e5 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -28,36 +28,30 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { {} /** - * @notice Deposits an `_amount` of vault collateral assets - * from the this strategy contract to the Balancer pool. - * @param _strategyAsset Address of the Vault collateral asset - * @param _strategyAmount The amount of Vault collateral assets to deposit + * @notice There are no plans to configure BalancerMetaPool as a default + * asset strategy. For that reason there is no need to support this + * functionality. */ - function deposit(address _strategyAsset, uint256 _strategyAmount) + function deposit(address, uint256) external override onlyVault nonReentrant { - address[] memory strategyAssets = new address[](1); - uint256[] memory strategyAmounts = new uint256[](1); - strategyAssets[0] = _strategyAsset; - strategyAmounts[0] = _strategyAmount; - - _deposit(strategyAssets, strategyAmounts); + revert("Not supported"); } /** - * @notice Deposits specified vault collateral assets - * from the this strategy contract to the Balancer pool. - * @param _strategyAssets Address of the Vault collateral assets - * @param _strategyAmounts The amount of each asset to deposit + * @notice There are no plans to configure BalancerMetaPool as a default + * asset strategy. For that reason there is no need to support this + * functionality. */ - function deposit( - address[] memory _strategyAssets, - uint256[] memory _strategyAmounts - ) external onlyVault nonReentrant { - _deposit(_strategyAssets, _strategyAmounts); + function deposit(address[] memory, uint256[] memory) + external + onlyVault + nonReentrant + { + revert("Not supported"); } /** @@ -135,8 +129,13 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { } } - uint256 minBPT = getBPTExpected(_strategyAssets, _strategyAmounts); - uint256 minBPTwSlippage = minBPT.mulTruncate(1e18 - maxDepositSlippage); + uint256 minBPT = getBPTExpected( + strategyAssetsToPoolAssets, + strategyAssetAmountsToPoolAssetAmounts + ); + uint256 minBPTwDeviation = minBPT.mulTruncate( + 1e18 - maxDepositDeviation + ); /* EXACT_TOKENS_IN_FOR_BPT_OUT: * User sends precise quantities of tokens, and receives an @@ -148,7 +147,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { bytes memory userData = abi.encode( IBalancerVault.WeightedPoolJoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, amountsIn, - minBPTwSlippage + minBPTwDeviation ); IBalancerVault.JoinPoolRequest memory request = IBalancerVault @@ -222,27 +221,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { ); } - // STEP 1 - Calculate the max about of Balancer Pool Tokens (BPT) to withdraw - - // Estimate the required amount of Balancer Pool Tokens (BPT) for the assets - uint256 maxBPTtoWithdraw = getBPTExpected( - _strategyAssets, - _strategyAmounts - ); - // Increase BPTs by the max allowed slippage - // Any excess BPTs will be left in this strategy contract - maxBPTtoWithdraw = maxBPTtoWithdraw.mulTruncate( - 1e18 + maxWithdrawalSlippage - ); - - // STEP 2 - Withdraw the Balancer Pool Tokens (BPT) from Aura to this strategy contract - - // Withdraw BPT from Aura allowing for BPTs left in this strategy contract from previous withdrawals - _lpWithdraw( - maxBPTtoWithdraw - IERC20(platformAddress).balanceOf(address(this)) - ); - - // STEP 3 - Calculate the Balancer pool assets and amounts from the vault collateral assets + // STEP 1 - Calculate the Balancer pool assets and amounts from the vault collateral assets // Get all the supported balancer pool assets (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( @@ -292,6 +271,29 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { } } + // STEP 2 - Calculate the max about of Balancer Pool Tokens (BPT) to withdraw + + // Estimate the required amount of Balancer Pool Tokens (BPT) for the assets + uint256 maxBPTtoWithdraw = getBPTExpected( + poolAssets, + /* all non 0 values are overshot by 2 WEI and with the expected mainnet + * ~1% withdrawal deviation, the 2 WEI aren't important + */ + poolAssetsAmountsOut + ); + // Increase BPTs by the max allowed deviation + // Any excess BPTs will be left in this strategy contract + maxBPTtoWithdraw = maxBPTtoWithdraw.mulTruncate( + 1e18 + maxWithdrawalDeviation + ); + + // STEP 3 - Withdraw the Balancer Pool Tokens (BPT) from Aura to this strategy contract + + // Withdraw BPT from Aura allowing for BPTs left in this strategy contract from previous withdrawals + _lpWithdraw( + maxBPTtoWithdraw - IERC20(platformAddress).balanceOf(address(this)) + ); + // STEP 4 - Withdraw the balancer pool assets from the pool /* Custom asset exit: BPT_IN_FOR_EXACT_TOKENS_OUT: @@ -332,10 +334,10 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { ); // STEP 5 - Re-deposit any left over BPT tokens back into Aura - /* When concluding how much of BPT we need to withdraw from Aura we rely on Oracle prices - * and those can be stale (most ETH based have 24 hour heartbeat & 2% price change trigger) - * After exiting the pool strategy could have left over BPT tokens that are not earning - * boosted yield. We re-deploy those back in. + /* When concluding how much of BPT we need to withdraw from Aura we overshoot by + * roughly around 1% (initial mainnet setting of maxWithdrawalDeviation). After exiting + * the pool strategy could have left over BPT tokens that are not earning boosted yield. + * We re-deploy those back in. */ _lpDepositAll(); @@ -400,7 +402,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { poolAssets[i] = address(tokens[i]); minAmountsOut[i] = balances[i] .mulTruncate(strategyShare) - .mulTruncate(1e18 - maxWithdrawalSlippage); + .mulTruncate(1e18 - maxWithdrawalDeviation); } // STEP 3 - Withdraw the Balancer pool assets from the pool diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index df4b0c3377..96a567ffb7 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -31,10 +31,10 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { /// @notice Balancer pool identifier bytes32 public immutable balancerPoolId; - // Max withdrawal slippage denominated in 1e18 (1e18 == 100%) - uint256 public maxWithdrawalSlippage; - // Max deposit slippage denominated in 1e18 (1e18 == 100%) - uint256 public maxDepositSlippage; + // Max withdrawal deviation denominated in 1e18 (1e18 == 100%) + uint256 public maxWithdrawalDeviation; + // Max deposit deviation denominated in 1e18 (1e18 == 100%) + uint256 public maxDepositDeviation; int256[48] private __reserved; @@ -48,13 +48,13 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { bytes32 balancerPoolId; // Balancer pool identifier } - event MaxWithdrawalSlippageUpdated( - uint256 _prevMaxSlippagePercentage, - uint256 _newMaxSlippagePercentage + event MaxWithdrawalDeviationUpdated( + uint256 _prevMaxDeviationPercentage, + uint256 _newMaxDeviationPercentage ); - event MaxDepositSlippageUpdated( - uint256 _prevMaxSlippagePercentage, - uint256 _newMaxSlippagePercentage + event MaxDepositDeviationUpdated( + uint256 _prevMaxDeviationPercentage, + uint256 _newMaxDeviationPercentage ); /** @@ -99,11 +99,11 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { address[] calldata _assets, address[] calldata _pTokens ) external override onlyGovernor initializer { - maxWithdrawalSlippage = 1e15; - maxDepositSlippage = 1e15; + maxWithdrawalDeviation = 1e16; + maxDepositDeviation = 1e16; - emit MaxWithdrawalSlippageUpdated(0, maxWithdrawalSlippage); - emit MaxDepositSlippageUpdated(0, maxDepositSlippage); + emit MaxWithdrawalDeviationUpdated(0, maxWithdrawalDeviation); + emit MaxDepositDeviationUpdated(0, maxDepositDeviation); IERC20[] memory poolAssets = getPoolAssets(); require( @@ -225,28 +225,37 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { /* solhint-disable max-line-length */ /** - * @notice BPT price is calculated by dividing the pool (sometimes wrapped) market price by the - * rateProviderRate of that asset. To get BPT expected we need to multiply that by underlying - * asset amount divided by BPT token rate. BPT token rate is similar to Curve's virtual_price - * and expresses how much has the price of BPT appreciated in relation to the underlying assets. + * @notice BPT price is calculated by taking the rate from the rateProvider of the asset in + * question. If one does not exist it defaults to 1e18. To get the final BPT expected that + * is multiplied by the underlying asset amount divided by BPT token rate. BPT token rate is + * similar to Curve's virtual_price and expresses how much has the price of BPT appreciated + * (e.g. due to swap fees) in relation to the underlying assets * - * @dev - * bptPrice = pool_asset_oracle_price / pool_asset_rate + * Using the above approach makes the strategy vulnerable to a possible MEV attack using + * flash loan to manipulate the pool before a deposit/withdrawal since the function ignores + * market values of the assets being priced in BPT. + * + * At the time of writing there is no safe on-chain approach to pricing BPT in a way that it + * would make it invulnerable to MEV pool manipulation. See recent Balancer exploit: + * https://www.notion.so/originprotocol/Balancer-OETH-strategy-9becdea132704e588782a919d7d471eb?pvs=4#1cf07de12fc64f1888072321e0644348 * - * Since we only have oracle prices for the unwrapped version of the assets the equation - * turns into: + * To mitigate MEV possibilities during deposits and withdraws, the VaultValueChecker will use checkBalance before and after the move + * to ensure the expected changes took place. * - * bptPrice = from_pool_token(asset_amount).amount * oracle_price / pool_asset_rate + * @param _asset Address of the Balancer pool asset + * @param _amount Amount of the Balancer pool asset + * @return bptExpected of BPT expected in exchange for the asset * - * bptExpected = bptPrice(in relation to specified asset) * asset_amount / BPT_token_rate + * @dev + * bptAssetPrice = 1e18 (asset peg) * pool_asset_rate * - * and since from_pool_token(asset_amount).amount and pool_asset_rate cancel each-other out - * this makes the final equation: + * bptExpected = bptAssetPrice * asset_amount / BPT_token_rate * - * bptExpected = oracle_price * asset_amount / BPT_token_rate + * bptExpected = 1e18 (asset peg) * pool_asset_rate * asset_amount / BPT_token_rate + * bptExpected = asset_amount * pool_asset_rate / BPT_token_rate * - * more explanation here: - * https://www.notion.so/originprotocol/Support-Balancer-OETH-strategy-9becdea132704e588782a919d7d471eb?pvs=4#382834f9815e46a7937f3acca0f637c5 + * further information available here: + * https://www.notion.so/originprotocol/Balancer-OETH-strategy-9becdea132704e588782a919d7d471eb?pvs=4#ce01495ae70346d8971f5dced809fb83 */ /* solhint-enable max-line-length */ function getBPTExpected(address _asset, uint256 _amount) @@ -255,13 +264,9 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { virtual returns (uint256 bptExpected) { - address priceProvider = IVault(vaultAddress).priceProvider(); - uint256 strategyAssetMarketPrice = IOracle(priceProvider).price(_asset); uint256 bptRate = IRateProvider(platformAddress).getRate(); - - bptExpected = _amount - .mulTruncate(strategyAssetMarketPrice) - .divPrecisely(bptRate); + uint256 poolAssetRate = getRateProviderRate(_asset); + bptExpected = _amount.mulTruncate(poolAssetRate).divPrecisely(bptRate); } function getBPTExpected(address[] memory _assets, uint256[] memory _amounts) @@ -270,17 +275,12 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { virtual returns (uint256 bptExpected) { - // Get the oracle from the OETH Vault - address priceProvider = IVault(vaultAddress).priceProvider(); + require(_assets.length == _amounts.length, "Assets & amounts mismatch"); for (uint256 i = 0; i < _assets.length; ++i) { - uint256 strategyAssetMarketPrice = IOracle(priceProvider).price( - _assets[i] - ); + uint256 poolAssetRate = getRateProviderRate(_assets[i]); // convert asset amount to ETH amount - bptExpected = - bptExpected + - _amounts[i].mulTruncate(strategyAssetMarketPrice); + bptExpected += _amounts[i].mulTruncate(poolAssetRate); } uint256 bptRate = IRateProvider(platformAddress).getRate(); @@ -431,50 +431,50 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } /** - * @notice Sets max withdrawal slippage that is considered when removing + * @notice Sets max withdrawal deviation that is considered when removing * liquidity from Balancer pools. - * @param _maxWithdrawalSlippage Max withdrawal slippage denominated in + * @param _maxWithdrawalDeviation Max withdrawal deviation denominated in * wad (number with 18 decimals): 1e18 == 100%, 1e16 == 1% * - * IMPORTANT Minimum maxWithdrawalSlippage should actually be 0.1% (1e15) - * for production usage. Contract allows as low value as 0% for confirming - * correct behavior in test suite. + * IMPORTANT Minimum maxWithdrawalDeviation will be 1% (1e16) for production + * usage. Vault value checker in combination with checkBalance will + * catch any unexpected manipulation. */ - function setMaxWithdrawalSlippage(uint256 _maxWithdrawalSlippage) + function setMaxWithdrawalDeviation(uint256 _maxWithdrawalDeviation) external onlyVaultOrGovernorOrStrategist { require( - _maxWithdrawalSlippage <= 1e18, - "Max withdrawal slippage needs to be between 0% - 100%" + _maxWithdrawalDeviation <= 1e18, + "Withdrawal dev. out of bounds" ); - emit MaxWithdrawalSlippageUpdated( - maxWithdrawalSlippage, - _maxWithdrawalSlippage + emit MaxWithdrawalDeviationUpdated( + maxWithdrawalDeviation, + _maxWithdrawalDeviation ); - maxWithdrawalSlippage = _maxWithdrawalSlippage; + maxWithdrawalDeviation = _maxWithdrawalDeviation; } /** - * @notice Sets max deposit slippage that is considered when adding + * @notice Sets max deposit deviation that is considered when adding * liquidity to Balancer pools. - * @param _maxDepositSlippage Max deposit slippage denominated in + * @param _maxDepositDeviation Max deposit deviation denominated in * wad (number with 18 decimals): 1e18 == 100%, 1e16 == 1% * - * IMPORTANT Minimum maxDepositSlippage should actually be 0.1% (1e15) - * for production usage. Contract allows as low value as 0% for confirming - * correct behavior in test suite. + * IMPORTANT Minimum maxDepositDeviation will default to 1% (1e16) + * for production usage. Vault value checker in combination with + * checkBalance will catch any unexpected manipulation. */ - function setMaxDepositSlippage(uint256 _maxDepositSlippage) + function setMaxDepositDeviation(uint256 _maxDepositDeviation) external onlyVaultOrGovernorOrStrategist { - require( - _maxDepositSlippage <= 1e18, - "Max deposit slippage needs to be between 0% - 100%" + require(_maxDepositDeviation <= 1e18, "Deposit dev. out of bounds"); + emit MaxDepositDeviationUpdated( + maxDepositDeviation, + _maxDepositDeviation ); - emit MaxDepositSlippageUpdated(maxDepositSlippage, _maxDepositSlippage); - maxDepositSlippage = _maxDepositSlippage; + maxDepositDeviation = _maxDepositDeviation; } function _approveBase() internal virtual { diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 2dd2bf9850..e98459e8f7 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -1,5 +1,6 @@ const hre = require("hardhat"); const { ethers } = hre; +const { BigNumber } = ethers; const { formatUnits } = require("ethers/lib/utils"); const addresses = require("../utils/addresses"); @@ -82,6 +83,10 @@ const defaultFixture = deployments.createFixture(async () => { const ousd = await ethers.getContractAt("OUSD", ousdProxy.address); const vault = await ethers.getContractAt("IVault", vaultProxy.address); + const vaultValueChecker = await ethers.getContract("VaultValueChecker"); + const oethVaultValueChecker = await ethers.getContract( + "OETHVaultValueChecker" + ); const oethProxy = await ethers.getContract("OETHProxy"); const OETHVaultProxy = await ethers.getContract("OETHVaultProxy"); const oethVault = await ethers.getContractAt( @@ -530,6 +535,7 @@ const defaultFixture = deployments.createFixture(async () => { // Contracts ousd, vault, + vaultValueChecker, harvester, dripper, mockNonRebasing, @@ -608,6 +614,7 @@ const defaultFixture = deployments.createFixture(async () => { // OETH oethVault, + oethVaultValueChecker, oeth, frxETH, sfrxETH, @@ -910,6 +917,62 @@ async function convexVaultFixture() { return fixture; } +/* Deposit WETH liquidity in Balancer metaStable WETH pool to simulate + * MEV attack. + */ +async function tiltBalancerMetaStableWETHPool({ + // how much of pool TVL should be deposited. 100 == 100% + percentageOfTVLDeposit = 100, + attackerSigner, + balancerPoolId, + assetAddressArray, + wethIndex, + bptToken, + balancerVault, + reth, + weth, +}) { + const amountsIn = Array(assetAddressArray.length).fill(BigNumber.from("0")); + // calculate the amount of WETH that should be deposited in relation to pool TVL + amountsIn[wethIndex] = (await bptToken.totalSupply()) + .mul(BigNumber.from(percentageOfTVLDeposit)) + .div(BigNumber.from("100")); + + /* encode user data for pool joining + * + * EXACT_TOKENS_IN_FOR_BPT_OUT: + * User sends precise quantities of tokens, and receives an + * estimated but unknown (computed at run time) quantity of BPT. + * + * ['uint256', 'uint256[]', 'uint256'] + * [EXACT_TOKENS_IN_FOR_BPT_OUT, amountsIn, minimumBPT] + */ + const userData = ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256[]", "uint256"], + [1, amountsIn, BigNumber.from("0")] + ); + + await reth + .connect(attackerSigner) + .approve(balancerVault.address, oethUnits("1").mul(oethUnits("1"))); // 1e36 + await weth + .connect(attackerSigner) + .approve(balancerVault.address, oethUnits("1").mul(oethUnits("1"))); // 1e36 + + await balancerVault.connect(attackerSigner).joinPool( + balancerPoolId, // poolId + attackerSigner.address, // sender + attackerSigner.address, // recipient + [ + //JoinPoolRequest + assetAddressArray, // assets + amountsIn, // maxAmountsIn + userData, // userData + false, // fromInternalBalance + ] + ); +} + /** * Configure a Vault with the balancerREthStrategy */ @@ -972,6 +1035,7 @@ async function balancerWstEthFixture() { deployName: "99999_balancer_wstETH_WETH", forceDeploy: true, deployerIsProposer: true, + reduceQueueTime: true, }, proxyContractName: "OETHBalancerMetaPoolwstEthStrategyProxy", @@ -1409,6 +1473,20 @@ async function impersonateAccount(address) { }); } +async function nodeSnapshot() { + return await hre.network.provider.request({ + method: "evm_snapshot", + params: [], + }); +} + +async function nodeRevert(snapshotId) { + return await hre.network.provider.request({ + method: "evm_revert", + params: [snapshotId], + }); +} + async function _hardhatSetBalance(address, amount = "10000") { await hre.network.provider.request({ method: "hardhat_setBalance", @@ -1951,6 +2029,7 @@ module.exports = { impersonateAccount, balancerREthFixture, balancerWstEthFixture, + tiltBalancerMetaStableWETHPool, fraxETHStrategyFixture, oethMorphoAaveFixture, mintWETH, @@ -1959,4 +2038,6 @@ module.exports = { oethCollateralSwapFixture, ousdCollateralSwapFixture, fluxStrategyFixture, + nodeSnapshot, + nodeRevert, }; diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 5e0de93570..9f3af6aeca 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -1,5 +1,5 @@ const { expect } = require("chai"); -const { formatUnits, parseUnits } = require("ethers").utils; +const { formatUnits } = require("ethers").utils; const { BigNumber } = require("ethers"); const addresses = require("../../utils/addresses"); @@ -10,8 +10,12 @@ const { balancerWstEthFixture, impersonateAndFundContract, createFixtureLoader, + mintWETH, + tiltBalancerMetaStableWETHPool, } = require("../_fixture"); +const temporaryFork = require("../../utils/temporaryFork"); + const log = require("../../utils/logger")("test:fork:strategy:balancer"); const loadBalancerREthFixtureDefault = createFixtureLoader( @@ -38,7 +42,7 @@ forkOnlyDescribe( let fixture; - describe.only("Post deployment", () => { + describe("Post deployment", () => { beforeEach(async () => { fixture = await loadBalancerREthFixtureDefault(); }); @@ -64,13 +68,14 @@ forkOnlyDescribe( addresses.mainnet.rETH_WETH_AuraRewards ); - // Check slippage values - expect(await balancerREthStrategy.maxDepositSlippage()).to.equal( - oethUnits("0.001") + // Check deviation values + expect(await balancerREthStrategy.maxDepositDeviation()).to.equal( + oethUnits("0.01") ); - expect(await balancerREthStrategy.maxWithdrawalSlippage()).to.equal( - oethUnits("0.001") + expect(await balancerREthStrategy.maxWithdrawalDeviation()).to.equal( + oethUnits("0.01") ); + // Check addresses expect(await balancerREthStrategy.rETH()).to.equal( addresses.mainnet.rETH @@ -90,7 +95,7 @@ forkOnlyDescribe( }); }); - describe.only("Deposit", function () { + describe("Deposit", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureNotDefault(); }); @@ -144,7 +149,7 @@ forkOnlyDescribe( ).to.approxEqualTolerance(rethValue.add(wethUnits), 0.01); }); - it("Should be able to deposit with higher deposit slippage", async function () {}); + it("Should be able to deposit with higher deposit deviation", async function () {}); it("Should revert when read-only re-entrancy is triggered", async function () { /* - needs to be an asset default strategy @@ -168,7 +173,7 @@ forkOnlyDescribe( }); }); - describe.only("Withdraw", function () { + describe("Withdraw", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureNotDefault(); const { balancerREthStrategy, oethVault, strategist, reth, weth } = @@ -291,10 +296,10 @@ forkOnlyDescribe( expect(stEthBalanceDiff).to.be.gte(await units("15", reth), 1); }); - it("Should be able to withdraw with higher withdrawal slippage", async function () {}); + it("Should be able to withdraw with higher withdrawal deviation", async function () {}); }); - describe.only("Large withdraw", function () { + describe("Large withdraw", function () { const depositAmount = 30000; let depositAmountUnits, oethVaultSigner; beforeEach(async () => { @@ -368,7 +373,7 @@ forkOnlyDescribe( weth, } = fixture; - const withdrawAmount = 29950; + const withdrawAmount = 29690; const withdrawAmountUnits = oethUnits(withdrawAmount.toString(), 18); const stratValueBefore = await oethVault.totalValue(); @@ -414,7 +419,6 @@ forkOnlyDescribe( balancerREthStrategy, rEthBPT, oethVault, - timelock, reth, weth, auraPool, @@ -431,10 +435,6 @@ forkOnlyDescribe( const withdrawAmount = 29700; const withdrawAmountUnits = oethUnits(withdrawAmount.toString(), 18); - await balancerREthStrategy - .connect(timelock) - .setMaxWithdrawalSlippage(parseUnits("1", 16)); // 1% - // Withdraw WETH // prettier-ignore await balancerREthStrategy @@ -502,7 +502,7 @@ forkOnlyDescribe( }); }); - describe.only("Harvest rewards", function () { + describe("Harvest rewards", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureDefault(); }); @@ -521,7 +521,7 @@ forkOnlyDescribe( forkOnlyDescribe( "ForkTest: Balancer MetaStablePool wstETH/WETH Strategy", function () { - describe.only("Deposit", function () { + describe("Deposit", function () { let fixture; beforeEach(async () => { @@ -561,7 +561,7 @@ forkOnlyDescribe( }); }); - describe.only("Withdraw", function () { + describe("Withdraw", function () { let fixture; beforeEach(async () => { @@ -576,11 +576,6 @@ forkOnlyDescribe( [weth.address, stETH.address], [units("25", weth), oethUnits("25")] ); - - // TODO: Check slippage errors - await balancerWstEthStrategy - .connect(strategist) - .setMaxWithdrawalSlippage(oethUnits("0.01")); }); it("Should be able to withdraw 10 WETH from the pool", async function () { @@ -697,7 +692,7 @@ forkOnlyDescribe( }); }); - describe.only("Harvest rewards", function () { + describe("Harvest rewards", function () { it("Should be able to collect reward tokens", async function () { const { josh, balancerWstEthStrategy, oethHarvester } = await loadBalancerWstEthFixture(); @@ -708,6 +703,246 @@ forkOnlyDescribe( ](balancerWstEthStrategy.address); }); }); + + describe("work in MEV environment", function () { + let attackerAddress; + let sAttacker; + let fixture; + + beforeEach(async () => { + fixture = await loadBalancerREthFixtureNotDefault(); + + attackerAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; + sAttacker = await impersonateAndFundContract(attackerAddress); + await mintWETH(fixture.weth, sAttacker, "500000"); + }); + + it("deposit should fail if pool is being manipulated", async function () { + const { + balancerREthStrategy, + oethVault, + oethVaultValueChecker, + oeth, + weth, + reth, + rEthBPT, + josh, + balancerVault, + } = fixture; + let forkedStratBalance = 0; + const { vaultChange, profit } = await temporaryFork({ + temporaryAction: async () => { + await depositTest(fixture, [5, 5], [weth, reth], rEthBPT); + forkedStratBalance = await balancerREthStrategy["checkBalance()"](); + }, + vaultContract: oethVault, + oTokenContract: oeth, + }); + + expect(forkedStratBalance).to.be.gte(await oethUnits("0"), 1); + const stratBalance = await balancerREthStrategy["checkBalance()"](); + expect(stratBalance).to.equal(await oethUnits("0"), 1); + + const { profit: profitWithTilt } = await temporaryFork({ + temporaryAction: async () => { + await tiltBalancerMetaStableWETHPool({ + percentageOfTVLDeposit: 300, // 300% + attackerSigner: sAttacker, + balancerPoolId: await balancerREthStrategy.balancerPoolId(), + assetAddressArray: [reth.address, weth.address], + wethIndex: 1, + bptToken: rEthBPT, + balancerVault, + reth, + weth, + }); + + await oethVaultValueChecker.connect(josh).takeSnapshot(); + await depositTest(fixture, [5, 5], [weth, reth], rEthBPT, 20); + + await expect( + oethVaultValueChecker.connect(josh).checkDelta( + profit, // expected profit + oethUnits("0.1"), // profit variance + vaultChange, // expected vaultChange + oethUnits("0.1") // expected vaultChange variance + ) + ).to.be.revertedWith("Profit too high"); + }, + vaultContract: oethVault, + oTokenContract: oeth, + }); + + const profitDiff = profitWithTilt.sub(profit); + expect(profitDiff).to.be.gte(oethUnits("0.3"), 1); + }); + + it("withdrawal should fail if pool is being manipulated maxWithdrawalDeviation catching the issue", async function () { + const { + balancerREthStrategy, + oethVault, + oeth, + weth, + reth, + rEthBPT, + balancerVault, + } = fixture; + + const wethWithdrawAmount = oethUnits("0"); + const rethWithdrawAmount = oethUnits("7"); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + await depositTest(fixture, [10, 10], [weth, reth], rEthBPT); + + await temporaryFork({ + temporaryAction: async () => { + await tiltBalancerMetaStableWETHPool({ + percentageOfTVLDeposit: 300, // 300% + attackerSigner: sAttacker, + balancerPoolId: await balancerREthStrategy.balancerPoolId(), + assetAddressArray: [reth.address, weth.address], + wethIndex: 1, + bptToken: rEthBPT, + balancerVault, + reth, + weth, + }); + + // prettier-ignore + expect( + balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( + oethVault.address, + [reth.address, weth.address], + [rethWithdrawAmount, wethWithdrawAmount] + ) + // not enough BPT supplied + ).to.be.revertedWith("BAL#207"); + }, + vaultContract: oethVault, + oTokenContract: oeth, + }); + }); + + it("withdrawal should fail if pool is being manipulated maxWithdrawalDeviation NOT catching the issue and Vault Value checker catching it", async function () { + const { + balancerREthStrategy, + oethVault, + oethVaultValueChecker, + oeth, + weth, + reth, + rEthBPT, + josh, + balancerVault, + strategist, + } = fixture; + + const wethWithdrawAmount = oethUnits("0"); + const rethWithdrawAmount = oethUnits("5"); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + + await depositTest(fixture, [10, 10], [weth, reth], rEthBPT); + + // set max withdrawal deviation to 100% + await balancerREthStrategy + .connect(strategist) + .setMaxWithdrawalDeviation(oethUnits("1")); // 100% + + const { vaultChange, profit } = await temporaryFork({ + temporaryAction: async () => { + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( + oethVault.address, + [reth.address, weth.address], + [rethWithdrawAmount, wethWithdrawAmount] + ); + }, + vaultContract: oethVault, + oTokenContract: oeth, + }); + + const { profit: profitWithTilt } = await temporaryFork({ + temporaryAction: async () => { + await tiltBalancerMetaStableWETHPool({ + percentageOfTVLDeposit: 300, // 300% + attackerSigner: sAttacker, + balancerPoolId: await balancerREthStrategy.balancerPoolId(), + assetAddressArray: [reth.address, weth.address], + wethIndex: 1, + bptToken: rEthBPT, + balancerVault, + reth, + weth, + }); + + await oethVaultValueChecker.connect(josh).takeSnapshot(); + + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( + oethVault.address, + [reth.address, weth.address], + [rethWithdrawAmount, wethWithdrawAmount] + ); + + await expect( + oethVaultValueChecker.connect(josh).checkDelta( + profit, // expected profit + oethUnits("0.1"), // profit variance + vaultChange, // expected vaultChange + oethUnits("0.1") // expected vaultChange variance + ) + ).to.be.revertedWith("Profit too low"); + }, + vaultContract: oethVault, + oTokenContract: oeth, + }); + + const profitDiff = profitWithTilt.sub(profit); + expect(profitDiff).to.be.lte(oethUnits("-0.5"), 1); + }); + + it("checkBalance with ~100 units should almost not be affected by heavy pool manipulation", async function () { + const { balancerREthStrategy, weth, reth, rEthBPT, balancerVault } = + fixture; + + await depositTest(fixture, [50, 50], [weth, reth], rEthBPT); + + const checkBalanceAmount = await balancerREthStrategy[ + "checkBalance()" + ](); + expect(checkBalanceAmount).to.be.gte(oethUnits("0"), 1); + + await tiltBalancerMetaStableWETHPool({ + percentageOfTVLDeposit: 300, // 300% + attackerSigner: sAttacker, + balancerPoolId: await balancerREthStrategy.balancerPoolId(), + assetAddressArray: [reth.address, weth.address], + wethIndex: 1, + bptToken: rEthBPT, + balancerVault, + reth, + weth, + }); + + const checkBalanceAmountAfterTilt = await balancerREthStrategy[ + "checkBalance()" + ](); + expect(checkBalanceAmountAfterTilt).to.be.gte(await oethUnits("0"), 1); + // ~100 units in pool liquidity should have less than 0.02 effect == 0.02% + expect(checkBalanceAmountAfterTilt.sub(checkBalanceAmount)).to.be.lte( + oethUnits("0.02") + ); + }); + }); } ); @@ -752,7 +987,13 @@ async function getPoolBalances(balancerVault, pid) { return result; } -async function depositTest(fixture, amounts, allAssets, bpt) { +async function depositTest( + fixture, + amounts, + allAssets, + bpt, + strategyValueDiffPct = 1 +) { const { oethVault, oeth, @@ -800,7 +1041,10 @@ async function depositTest(fixture, amounts, allAssets, bpt) { const strategyValuesDiff = after.strategyValues.sum.sub( before.strategyValues.sum ); - expect(strategyValuesDiff).to.approxEqualTolerance(sumEthAmounts, 0.1); + expect(strategyValuesDiff).to.approxEqualTolerance( + sumEthAmounts, + strategyValueDiffPct + ); expect( after.strategyValues.value, "strategy total value = sum of asset values" diff --git a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js index 5bec3b2452..b97c775334 100644 --- a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js +++ b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js @@ -29,7 +29,7 @@ forkOnlyDescribe( fixture = await loadFixture(); }); - it.only("Should not allow read-only reentrancy", async () => { + it("Should not allow read-only reentrancy", async () => { const { weth, reth, oethVault, rEthBPT, balancerREthPID, daniel } = fixture; diff --git a/contracts/utils/temporaryFork.js b/contracts/utils/temporaryFork.js new file mode 100644 index 0000000000..792454e095 --- /dev/null +++ b/contracts/utils/temporaryFork.js @@ -0,0 +1,30 @@ +const hre = require("hardhat"); +const { nodeSnapshot, nodeRevert } = require("../test/_fixture"); +/* Executes a (test) function in a temporary fork that is after the function executes reverted. + * Useful for when preview of actions need to be executed and changes in oToken supply and vault + * observed. + */ +const temporaryFork = async ({ + temporaryAction, + vaultContract, + oTokenContract, +}) => { + const vaultValue = await vaultContract.totalValue(); + const totalSupply = await oTokenContract.totalSupply(); + const snapshotId = await nodeSnapshot(); + + await temporaryAction(); + + const vaultChange = (await vaultContract.totalValue()).sub(vaultValue); + const supplyChange = (await oTokenContract.totalSupply()).sub(totalSupply); + const profit = vaultChange.sub(supplyChange); + + await nodeRevert(snapshotId); + return { + vaultChange, + supplyChange, + profit, + }; +}; + +module.exports = temporaryFork; From 04b30107cf9b7b3a6c966714196604db81002192 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 22:03:37 +0200 Subject: [PATCH 44/67] M02 withdrawal fuzzing tests (#1801) * add more withdrawal tests * add more withdrawal cases --- .../balancerMetaStablePool.fork-test.js | 252 +++++++----------- 1 file changed, 91 insertions(+), 161 deletions(-) diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 9f3af6aeca..8de9e29824 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -184,90 +184,55 @@ forkOnlyDescribe( .depositToStrategy( balancerREthStrategy.address, [weth.address, reth.address], - [oethUnits("22"), oethUnits("25")] + [oethUnits("32"), oethUnits("32")] ); }); - it("Should be able to withdraw 10 WETH from the pool", async function () { - const { weth, balancerREthStrategy, oethVault } = fixture; - const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); - const withdrawAmount = await units("10", weth); - - const oethVaultSigner = await impersonateAndFundContract( - oethVault.address - ); - - // prettier-ignore - await balancerREthStrategy - .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( - oethVault.address, - weth.address, - withdrawAmount - ); - - const vaultWethBalanceAfter = await weth.balanceOf(oethVault.address); - const wethBalanceDiffVault = vaultWethBalanceAfter.sub( - vaultWethBalanceBefore - ); - expect(wethBalanceDiffVault).to.approxEqualTolerance( - withdrawAmount, - 0.01 - ); - }); - it("Should be able to withdraw 8 RETH from the pool", async function () { - const { reth, balancerREthStrategy, oethVault } = fixture; - - const vaultRethBalanceBefore = await reth.balanceOf(oethVault.address); - const withdrawAmount = await units("8", reth); - - const oethVaultSigner = await impersonateAndFundContract( - oethVault.address - ); - - // prettier-ignore - await balancerREthStrategy - .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( - oethVault.address, - reth.address, - withdrawAmount + // a list of WETH/RETH pairs + const withdrawalTestCases = [ + ["10", "0"], + ["0", "8"], + ["11", "14"], + ["2.9543", "9.234"], + ["1.0001", "0"], + ["9.99998", "0"], + ["0", "7.00123"], + ["0", "0.210002"], + ["38.432", "12.5643"], + ["5.123452", "29.00123"], + ["22.1232", "30.12342"], + ]; + + for (const [wethAmount, rethAmount] of withdrawalTestCases) { + + it(`Should be able to withdraw ${wethAmount} WETH and ${rethAmount} RETH from the pool`, async function () { + const { reth, balancerREthStrategy, oethVault, weth } = fixture; + + const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); + const vaultRethBalanceBefore = await reth.balanceOf(oethVault.address); + const wethWithdrawAmount = await units(wethAmount, weth); + const rethWithdrawAmount = await units(rethAmount, reth); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address ); - const vaultRethBalanceAfter = await reth.balanceOf(oethVault.address); - const rethBalanceDiffVault = vaultRethBalanceAfter.sub( - vaultRethBalanceBefore - ); - expect(rethBalanceDiffVault).to.approxEqualTolerance( - withdrawAmount, - 0.01 - ); - }); - it("Should be able to withdraw 11 WETH and 14 RETH from the pool", async function () { - const { reth, balancerREthStrategy, oethVault, weth } = fixture; - - const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); - const vaultRethBalanceBefore = await reth.balanceOf(oethVault.address); - const wethWithdrawAmount = await units("11", weth); - const rethWithdrawAmount = await units("14", reth); - - const oethVaultSigner = await impersonateAndFundContract( - oethVault.address - ); - - // prettier-ignore - await balancerREthStrategy - .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( - oethVault.address, - [weth.address, reth.address], - [wethWithdrawAmount, rethWithdrawAmount] - ); - - expect( - (await weth.balanceOf(oethVault.address)).sub(vaultWethBalanceBefore) - ).to.approxEqualTolerance(wethWithdrawAmount, 0.01); - expect( - (await reth.balanceOf(oethVault.address)).sub(vaultRethBalanceBefore) - ).to.approxEqualTolerance(rethWithdrawAmount, 0.01); - }); + // prettier-ignore + await balancerREthStrategy + .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( + oethVault.address, + [weth.address, reth.address], + [wethWithdrawAmount, rethWithdrawAmount] + ); + + expect( + (await weth.balanceOf(oethVault.address)).sub(vaultWethBalanceBefore) + ).to.approxEqualTolerance(wethWithdrawAmount, 0.01); + expect( + (await reth.balanceOf(oethVault.address)).sub(vaultRethBalanceBefore) + ).to.approxEqualTolerance(rethWithdrawAmount, 0.01); + }); + } it("Should be able to withdraw all of pool liquidity", async function () { const { oethVault, weth, reth, balancerREthStrategy } = fixture; @@ -574,95 +539,60 @@ forkOnlyDescribe( .depositToStrategy( balancerWstEthStrategy.address, [weth.address, stETH.address], - [units("25", weth), oethUnits("25")] + [units("35", weth), oethUnits("35")] ); }); - it("Should be able to withdraw 10 WETH from the pool", async function () { - const { weth, balancerWstEthStrategy, oethVault } = fixture; - - const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); - const withdrawAmount = await units("10", weth); - - const oethVaultSigner = await impersonateAndFundContract( - oethVault.address - ); - - // prettier-ignore - await balancerWstEthStrategy - .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( - oethVault.address, - weth.address, - withdrawAmount + // a list of WETH/STeth pairs + const withdrawalTestCases = [ + ["10", "0"], + ["0", "8"], + ["11", "14"], + ["2.9543", "9.234"], + ["1.0001", "0"], + ["9.99998", "0"], + ["0", "7.00123"], + ["0", "0.210002"], + ["38.432", "12.5643"], + ["5.123452", "29.00123"], + ["22.1232", "30.12342"], + ]; + + for (const [wethAmount, stETHAmount] of withdrawalTestCases) { + + it(`Should be able to withdraw ${wethAmount} WETH and ${stETHAmount} stETH from the pool`, async function () { + + const { stETH, balancerWstEthStrategy, oethVault, weth } = fixture; + + const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); + const vaultstEthBalanceBefore = await stETH.balanceOf( + oethVault.address ); + const wethWithdrawAmount = await units(wethAmount, weth); + const stETHWithdrawAmount = await units(stETHAmount, stETH); - const vaultWethBalanceAfter = await weth.balanceOf(oethVault.address); - const wethBalanceDiffVault = vaultWethBalanceAfter.sub( - vaultWethBalanceBefore - ); - expect(wethBalanceDiffVault).to.approxEqualTolerance(withdrawAmount, 1); - }); - - it("Should be able to withdraw 8 stETH from the pool", async function () { - const { stETH, balancerWstEthStrategy, oethVault } = fixture; - - const vaultstETHBalanceBefore = await stETH.balanceOf( - oethVault.address - ); - const withdrawAmount = await units("8", stETH); - - const oethVaultSigner = await impersonateAndFundContract( - oethVault.address - ); - - // prettier-ignore - await balancerWstEthStrategy - .connect(oethVaultSigner)["withdraw(address,address,uint256)"]( - oethVault.address, - stETH.address, - withdrawAmount - ); - - const vaultstETHBalanceAfter = await stETH.balanceOf(oethVault.address); - const stETHBalanceDiffVault = vaultstETHBalanceAfter.sub( - vaultstETHBalanceBefore - ); - expect(stETHBalanceDiffVault).to.approxEqualTolerance( - withdrawAmount, - 1 - ); - }); - it("Should be able to withdraw 11 WETH and 14 stETH from the pool", async function () { - const { stETH, balancerWstEthStrategy, oethVault, weth } = fixture; - - const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); - const vaultstEthBalanceBefore = await stETH.balanceOf( - oethVault.address - ); - const wethWithdrawAmount = await units("11", weth); - const stETHWithdrawAmount = await units("14", stETH); - - const oethVaultSigner = await impersonateAndFundContract( - oethVault.address - ); - - // prettier-ignore - await balancerWstEthStrategy - .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( - oethVault.address, - [weth.address, stETH.address], - [wethWithdrawAmount, stETHWithdrawAmount] + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address ); - expect( - (await weth.balanceOf(oethVault.address)).sub(vaultWethBalanceBefore) - ).to.approxEqualTolerance(wethWithdrawAmount, 1); - expect( - (await stETH.balanceOf(oethVault.address)).sub( - vaultstEthBalanceBefore - ) - ).to.approxEqualTolerance(stETHWithdrawAmount, 1); - }); + // prettier-ignore + await balancerWstEthStrategy + .connect(oethVaultSigner)["withdraw(address,address[],uint256[])"]( + oethVault.address, + [weth.address, stETH.address], + [wethWithdrawAmount, stETHWithdrawAmount] + ); + + expect( + (await weth.balanceOf(oethVault.address)).sub(vaultWethBalanceBefore) + ).to.approxEqualTolerance(wethWithdrawAmount, 1); + expect( + (await stETH.balanceOf(oethVault.address)).sub( + vaultstEthBalanceBefore + ) + ).to.approxEqualTolerance(stETHWithdrawAmount, 1); + }); + } it("Should be able to withdraw all of pool liquidity", async function () { const { oethVault, weth, stETH, balancerWstEthStrategy } = fixture; From 852afa437d3e5e3676bcd578e4ecf1e6242f365f Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 22:15:30 +0200 Subject: [PATCH 45/67] N02 gas inefficiencies (#1786) * gas optimisation * fix bad merge and prettier --- .../balancer/BalancerMetaPoolStrategy.sol | 14 ++++----- .../balancer/BaseBalancerStrategy.sol | 3 +- .../balancerMetaStablePool.fork-test.js | 29 ++++++++++++------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index d25b2734e5..cd8aacc236 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -46,7 +46,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { * asset strategy. For that reason there is no need to support this * functionality. */ - function deposit(address[] memory, uint256[] memory) + function deposit(address[] calldata, uint256[] calldata) external onlyVault nonReentrant @@ -101,7 +101,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { assetToPToken[strategyAsset] != address(0), "Unsupported asset" ); - strategyAssetsToPoolAssets[i] = toPoolAsset(_strategyAssets[i]); + strategyAssetsToPoolAssets[i] = toPoolAsset(strategyAsset); if (strategyAmount > 0) { emit Deposit(strategyAsset, platformAddress, strategyAmount); @@ -192,8 +192,8 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ function withdraw( address _recipient, - address[] memory _strategyAssets, - uint256[] memory _strategyAmounts + address[] calldata _strategyAssets, + uint256[] calldata _strategyAmounts ) external onlyVault nonReentrant { _withdraw(_recipient, _strategyAssets, _strategyAmounts); } @@ -240,11 +240,11 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { for (uint256 i = 0; i < tokens.length; ++i) { poolAssets[i] = address(tokens[i]); + // Convert the Balancer pool asset back to a vault collateral asset + address strategyAsset = fromPoolAsset(poolAssets[i]); + // for each of the vault assets for (uint256 j = 0; j < _strategyAssets.length; ++j) { - // Convert the Balancer pool asset back to a strategy asset - address strategyAsset = fromPoolAsset(poolAssets[i]); - // If the vault asset equals the vault asset mapped from the Balancer pool asset if (_strategyAssets[j] == strategyAsset) { (, poolAssetsAmountsOut[i]) = toPoolAsset( diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 96a567ffb7..ef5b1bf7fb 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -111,7 +111,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { "Pool assets length mismatch" ); for (uint256 i = 0; i < _assets.length; ++i) { - (address asset, ) = fromPoolAsset(address(poolAssets[i]), 0); + address asset = fromPoolAsset(address(poolAssets[i])); require(_assets[i] == asset, "Pool assets mismatch"); } @@ -399,7 +399,6 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { view returns (address asset, uint256 amount) { - amount = 0; if (poolAsset == wstETH) { asset = stETH; if (poolAmount > 0) { diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 8de9e29824..2a81cd0bdc 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -202,14 +202,17 @@ forkOnlyDescribe( ["5.123452", "29.00123"], ["22.1232", "30.12342"], ]; - - for (const [wethAmount, rethAmount] of withdrawalTestCases) { + for (const [wethAmount, rethAmount] of withdrawalTestCases) { it(`Should be able to withdraw ${wethAmount} WETH and ${rethAmount} RETH from the pool`, async function () { const { reth, balancerREthStrategy, oethVault, weth } = fixture; - const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); - const vaultRethBalanceBefore = await reth.balanceOf(oethVault.address); + const vaultWethBalanceBefore = await weth.balanceOf( + oethVault.address + ); + const vaultRethBalanceBefore = await reth.balanceOf( + oethVault.address + ); const wethWithdrawAmount = await units(wethAmount, weth); const rethWithdrawAmount = await units(rethAmount, reth); @@ -226,10 +229,14 @@ forkOnlyDescribe( ); expect( - (await weth.balanceOf(oethVault.address)).sub(vaultWethBalanceBefore) + (await weth.balanceOf(oethVault.address)).sub( + vaultWethBalanceBefore + ) ).to.approxEqualTolerance(wethWithdrawAmount, 0.01); expect( - (await reth.balanceOf(oethVault.address)).sub(vaultRethBalanceBefore) + (await reth.balanceOf(oethVault.address)).sub( + vaultRethBalanceBefore + ) ).to.approxEqualTolerance(rethWithdrawAmount, 0.01); }); } @@ -559,12 +566,12 @@ forkOnlyDescribe( ]; for (const [wethAmount, stETHAmount] of withdrawalTestCases) { - it(`Should be able to withdraw ${wethAmount} WETH and ${stETHAmount} stETH from the pool`, async function () { - const { stETH, balancerWstEthStrategy, oethVault, weth } = fixture; - const vaultWethBalanceBefore = await weth.balanceOf(oethVault.address); + const vaultWethBalanceBefore = await weth.balanceOf( + oethVault.address + ); const vaultstEthBalanceBefore = await stETH.balanceOf( oethVault.address ); @@ -584,7 +591,9 @@ forkOnlyDescribe( ); expect( - (await weth.balanceOf(oethVault.address)).sub(vaultWethBalanceBefore) + (await weth.balanceOf(oethVault.address)).sub( + vaultWethBalanceBefore + ) ).to.approxEqualTolerance(wethWithdrawAmount, 1); expect( (await stETH.balanceOf(oethVault.address)).sub( From abf482fc314919921d3a300b42e13d44fa4de86f Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 22:16:05 +0200 Subject: [PATCH 46/67] remove todo comments (#1796) --- .../strategies/balancer/BalancerMetaPoolStrategy.sol | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index cd8aacc236..bcf86a532a 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -327,8 +327,9 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { balancerVault.exitPool( balancerPoolId, address(this), - // TODO: this is incorrect and should be altered when/if we intend to support - // pools that deal with native ETH + /* Payable keyword is required because of the IBalancerVault interface even though + * this strategy shall never be receiving native ETH + */ payable(address(this)), request ); @@ -425,8 +426,9 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { balancerVault.exitPool( balancerPoolId, address(this), - // TODO: this is incorrect and should be altered when/if we intend to support - // pools that deal with native ETH + /* Payable keyword is required because of the IBalancerVault interface even though + * this strategy shall never be receiving native ETH + */ payable(address(this)), request ); From d159fbe2f94e279fbb5432a94c82f480ae531047 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 22:21:05 +0200 Subject: [PATCH 47/67] use a more appropriate array initialisation length (#1800) --- .../strategies/balancer/BalancerMetaPoolStrategy.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index bcf86a532a..62d7bd943b 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -87,10 +87,10 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { ); uint256[] memory strategyAssetAmountsToPoolAssetAmounts = new uint256[]( - tokens.length + _strategyAssets.length ); address[] memory strategyAssetsToPoolAssets = new address[]( - tokens.length + _strategyAssets.length ); for (uint256 i = 0; i < _strategyAssets.length; ++i) { From e09a9b9238b1e3a3a42f04fb9ff158487b99a7da Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 22:23:59 +0200 Subject: [PATCH 48/67] more consistant function naming (#1797) --- .../strategies/balancer/BalancerMetaPoolStrategy.sol | 6 +++--- .../strategies/balancer/BaseBalancerStrategy.sol | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 62d7bd943b..7bb2e7619f 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -129,7 +129,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { } } - uint256 minBPT = getBPTExpected( + uint256 minBPT = _getBPTExpected( strategyAssetsToPoolAssets, strategyAssetAmountsToPoolAssetAmounts ); @@ -274,7 +274,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { // STEP 2 - Calculate the max about of Balancer Pool Tokens (BPT) to withdraw // Estimate the required amount of Balancer Pool Tokens (BPT) for the assets - uint256 maxBPTtoWithdraw = getBPTExpected( + uint256 maxBPTtoWithdraw = _getBPTExpected( poolAssets, /* all non 0 values are overshot by 2 WEI and with the expected mainnet * ~1% withdrawal deviation, the 2 WEI aren't important @@ -528,7 +528,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { * @param _asset Address of the Balancer pool asset * @return rate of the corresponding asset */ - function getRateProviderRate(address _asset) + function _getRateProviderRate(address _asset) internal view override diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index ef5b1bf7fb..e965cdd5a9 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -105,7 +105,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { emit MaxWithdrawalDeviationUpdated(0, maxWithdrawalDeviation); emit MaxDepositDeviationUpdated(0, maxDepositDeviation); - IERC20[] memory poolAssets = getPoolAssets(); + IERC20[] memory poolAssets = _getPoolAssets(); require( poolAssets.length == _assets.length, "Pool assets length mismatch" @@ -185,7 +185,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * ETH units we need to convert the ETH denominated amount to asset amount. */ if (toPoolAsset(_asset) == _asset) { - amount = amount.divPrecisely(getRateProviderRate(_asset)); + amount = amount.divPrecisely(_getRateProviderRate(_asset)); } } @@ -258,7 +258,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * https://www.notion.so/originprotocol/Balancer-OETH-strategy-9becdea132704e588782a919d7d471eb?pvs=4#ce01495ae70346d8971f5dced809fb83 */ /* solhint-enable max-line-length */ - function getBPTExpected(address _asset, uint256 _amount) + function _getBPTExpected(address _asset, uint256 _amount) internal view virtual @@ -269,7 +269,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { bptExpected = _amount.mulTruncate(poolAssetRate).divPrecisely(bptRate); } - function getBPTExpected(address[] memory _assets, uint256[] memory _amounts) + function _getBPTExpected(address[] memory _assets, uint256[] memory _amounts) internal view virtual @@ -298,7 +298,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * @notice Balancer returns assets and rateProviders for corresponding assets ordered * by numerical order. */ - function getPoolAssets() internal view returns (IERC20[] memory assets) { + function _getPoolAssets() internal view returns (IERC20[] memory assets) { (assets, , ) = balancerVault.getPoolTokens(balancerPoolId); } @@ -482,7 +482,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { pToken.safeApprove(address(balancerVault), type(uint256).max); } - function getRateProviderRate(address _asset) + function _getRateProviderRate(address _asset) internal view virtual From daeab913fa50ef99054fd3a0c1f3af298fd0e070 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 22:24:27 +0200 Subject: [PATCH 49/67] fix typo (#1798) --- .../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 7bb2e7619f..00c63bec30 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -342,7 +342,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { */ _lpDepositAll(); - // STEP 6 - Unswap balancer pool assets to vault collateral assets and sent to the vault. + // STEP 6 - Unswap balancer pool assets to vault collateral assets and send to the vault. // For each of the specified assets for (uint256 i = 0; i < _strategyAssets.length; ++i) { From a2f8fcda0376e292df8a6ba832cf3d43dec36cbd Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 22:26:59 +0200 Subject: [PATCH 50/67] simplify the way we withdrawAll. no need to pass along min amonts (#1777) --- .../balancer/BalancerMetaPoolStrategy.sol | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 00c63bec30..cf0ee9c85f 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -380,40 +380,29 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { // STEP 1 - Withdraw all Balancer Pool Tokens (BPT) from Aura to this strategy contract _lpWithdrawAll(); - - // STEP 2 - Calculate the minumum amount of pool assets to accept for the BPTs - // Get the BPTs withdrawn from Aura plus any that were already in this strategy contract uint256 BPTtoWithdraw = IERC20(platformAddress).balanceOf( address(this) ); - // Get the balancer pool assets and their total balances - (IERC20[] memory tokens, uint256[] memory balances, ) = balancerVault - .getPoolTokens(balancerPoolId); - - // the strategy's share of the pool assets - uint256 strategyShare = BPTtoWithdraw.divPrecisely( - IERC20(platformAddress).totalSupply() - ); - + (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens(balancerPoolId); uint256[] memory minAmountsOut = new uint256[](tokens.length); address[] memory poolAssets = new address[](tokens.length); for (uint256 i = 0; i < tokens.length; ++i) { poolAssets[i] = address(tokens[i]); - minAmountsOut[i] = balances[i] - .mulTruncate(strategyShare) - .mulTruncate(1e18 - maxWithdrawalDeviation); } - // STEP 3 - Withdraw the Balancer pool assets from the pool - + // STEP 2 - Withdraw the Balancer pool assets from the pool /* Proportional exit: EXACT_BPT_IN_FOR_TOKENS_OUT: * User sends a precise quantity of BPT, and receives an estimated but unknown * (computed at run time) quantity of a single token * * ['uint256', 'uint256'] * [EXACT_BPT_IN_FOR_TOKENS_OUT, bptAmountIn] + * + * It is ok to pass an empty minAmountsOut since tilting the pool in any direction + * when doing a proportional exit can only be beneficial to the strategy. Since + * it will receive more of the underlying tokens for the BPT traded in. */ bytes memory userData = abi.encode( IBalancerVault.WeightedPoolExitKind.EXACT_BPT_IN_FOR_TOKENS_OUT, @@ -433,8 +422,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { request ); - // STEP 4 - Convert the balancer pool assets to the vault collateral assets and send to the vault - + // STEP 3 - Convert the balancer pool assets to the vault collateral assets and send to the vault // For each of the Balancer pool assets for (uint256 i = 0; i < tokens.length; ++i) { address poolAsset = address(tokens[i]); From cf4122acb9b12a4723afa9d4461b3b6303c150a4 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 30 Aug 2023 22:31:26 +0200 Subject: [PATCH 51/67] M03 - missing or misleading documentation (#1781) * improve documentation * add comma --- .../balancer/BalancerMetaPoolStrategy.sol | 13 +++++++++++++ .../strategies/balancer/BaseAuraStrategy.sol | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index cf0ee9c85f..99af48170e 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -73,6 +73,13 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { _deposit(strategyAssets, strategyAmounts); } + /* + * _deposit doesn't require a read-only re-entrancy protection since during the deposit + * the function enters the Balancer Vault Context. If this function were called as part of + * the attacking contract (while intercepting execution flow upon receiving ETH) the read-only + * protection of the Balancer Vault would be triggered. Since the attacking contract would + * already be in the Balancer Vault context and wouldn't be able to enter it again. + */ function _deposit( address[] memory _strategyAssets, uint256[] memory _strategyAmounts @@ -203,6 +210,12 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { * @param _recipient Address to receive the Vault collateral assets. Typically is the Vault. * @param _strategyAssets Addresses of the Vault collateral assets * @param _strategyAmounts The amounts of Vault collateral assets to withdraw + * + * _withdrawal doesn't require a read-only re-entrancy protection since during the withdrawal + * the function enters the Balancer Vault Context. If this function were called as part of + * the attacking contract (while intercepting execution flow upon receiving ETH) the read-only + * protection of the Balancer Vault would be triggered. Since the attacking contract would + * already be in the Balancer Vault context and wouldn't be able to enter it again. */ function _withdraw( address _recipient, diff --git a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol index 61cf8c81b2..aa2ed28060 100644 --- a/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseAuraStrategy.sol @@ -80,7 +80,9 @@ abstract contract BaseAuraStrategy is BaseBalancerStrategy { onlyHarvester nonReentrant { - // Collect BAL and AURA + /* Similar to Convex, calling this function collects both of the + * accrued BAL and AURA tokens. + */ IRewardStaking(auraRewardPoolAddress).getReward(); _collectRewardTokens(); } From fcc08f7fcf1a76c7f98194279db77a5aa9fbeecb Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 12:38:29 +0200 Subject: [PATCH 52/67] M01 More comprehensive test suite (#1780) * add tests for approving tokens and harvesting rewards * prettier and lint --- contracts/test/_fixture.js | 19 ++- .../balancerMetaStablePool.fork-test.js | 148 +++++++++++++++++- 2 files changed, 165 insertions(+), 2 deletions(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index e98459e8f7..274546051c 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -194,6 +194,8 @@ const defaultFixture = deployments.createFixture(async () => { chainlinkOracleFeedETH, crv, crvMinter, + aura, + bal, threePool, threePoolToken, metapoolToken, @@ -258,6 +260,8 @@ const defaultFixture = deployments.createFixture(async () => { fdai = await ethers.getContractAt(erc20Abi, addresses.mainnet.fDAI); fusdc = await ethers.getContractAt(erc20Abi, addresses.mainnet.fUSDC); fusdt = await ethers.getContractAt(erc20Abi, addresses.mainnet.fUSDT); + aura = await ethers.getContractAt(erc20Abi, addresses.mainnet.AURA); + bal = await ethers.getContractAt(erc20Abi, addresses.mainnet.BAL); crvMinter = await ethers.getContractAt( crvMinterAbi, @@ -631,6 +635,8 @@ const defaultFixture = deployments.createFixture(async () => { mockSwapper, swapper1Inch, mock1InchSwapRouter, + aura, + bal, }; }); @@ -1473,6 +1479,14 @@ async function impersonateAccount(address) { }); } +async function mineBlocks(blocksToMine) { + const hexBlocks = "0x" + Number(blocksToMine).toString(16); + await hre.network.provider.request({ + method: "hardhat_mine", + params: [hexBlocks], + }); +} + async function nodeSnapshot() { return await hre.network.provider.request({ method: "evm_snapshot", @@ -1503,7 +1517,9 @@ async function _hardhatSetBalance(address, amount = "10000") { async function impersonateAndFundContract(address, amount = "100000") { await impersonateAccount(address); - await _hardhatSetBalance(address, amount); + if (parseFloat(amount) > 0) { + await _hardhatSetBalance(address, amount); + } const signer = await ethers.provider.getSigner(address); signer.address = address; @@ -2038,6 +2054,7 @@ module.exports = { oethCollateralSwapFixture, ousdCollateralSwapFixture, fluxStrategyFixture, + mineBlocks, nodeSnapshot, nodeRevert, }; diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 2a81cd0bdc..aa6b7131dd 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -10,6 +10,7 @@ const { balancerWstEthFixture, impersonateAndFundContract, createFixtureLoader, + mineBlocks, mintWETH, tiltBalancerMetaStableWETHPool, } = require("../_fixture"); @@ -93,6 +94,88 @@ forkOnlyDescribe( addresses.mainnet.frxETH ); }); + + it("Should safeApproveAllTokens", async function () { + const { reth, rEthBPT, weth, balancerREthStrategy, timelock } = fixture; + const balancerVault = await balancerREthStrategy.balancerVault(); + const auraRewardPool = + await balancerREthStrategy.auraRewardPoolAddress(); + + const MAX = BigNumber.from( + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); + const ZERO = BigNumber.from(0); + const expectAllowanceRaw = async (expected, asset, owner, spender) => { + const allowance = await asset.allowance(owner, spender); + await expect(allowance).to.eq(expected); + }; + + const resetAllowance = async (asset, spender) => { + // strategy needs some ETH so it can execute the transactions + const strategySigner = await impersonateAndFundContract( + balancerREthStrategy.address, + "10" + ); + await asset.connect(strategySigner).approve(spender, ZERO); + }; + + await resetAllowance(reth, balancerVault); + await resetAllowance(weth, balancerVault); + await resetAllowance(rEthBPT, balancerVault); + await resetAllowance(rEthBPT, auraRewardPool); + + await expectAllowanceRaw( + ZERO, + reth, + balancerREthStrategy.address, + balancerVault + ); + await expectAllowanceRaw( + ZERO, + weth, + balancerREthStrategy.address, + balancerVault + ); + await expectAllowanceRaw( + ZERO, + rEthBPT, + balancerREthStrategy.address, + balancerVault + ); + await expectAllowanceRaw( + ZERO, + rEthBPT, + balancerREthStrategy.address, + auraRewardPool + ); + + await balancerREthStrategy.connect(timelock).safeApproveAllTokens(); + + await expectAllowanceRaw( + MAX, + reth, + balancerREthStrategy.address, + balancerVault + ); + await expectAllowanceRaw( + MAX, + weth, + balancerREthStrategy.address, + balancerVault + ); + await expectAllowanceRaw( + MAX, + rEthBPT, + balancerREthStrategy.address, + balancerVault + ); + await expectAllowanceRaw( + MAX, + rEthBPT, + balancerREthStrategy.address, + auraRewardPool + ); + }); }); describe("Deposit", function () { @@ -478,13 +561,76 @@ forkOnlyDescribe( beforeEach(async () => { fixture = await loadBalancerREthFixtureDefault(); }); + it("Should be able to collect reward tokens", async function () { - const { josh, balancerREthStrategy, oethHarvester } = fixture; + const { + weth, + timelock, + reth, + rEthBPT, + balancerREthStrategy, + oethHarvester, + bal, + aura, + } = fixture; + + const sHarvester = await impersonateAndFundContract( + oethHarvester.address + ); + expect(await bal.balanceOf(oethHarvester.address)).to.equal( + oethUnits("0") + ); + expect(await aura.balanceOf(oethHarvester.address)).to.equal( + oethUnits("0") + ); + + await balancerREthStrategy + .connect(timelock) + .setMaxDepositSlippage(parseUnits("1", 16)); // 1% + + await depositTest(fixture, [5, 5], [weth, reth], rEthBPT); + await mineBlocks(1000); + + await balancerREthStrategy.connect(sHarvester).collectRewardTokens(); + + expect(await bal.balanceOf(oethHarvester.address)).to.be.gte( + oethUnits("0") + ); + expect(await aura.balanceOf(oethHarvester.address)).to.be.gte( + oethUnits("0") + ); + }); + + it("Should be able to collect and swap reward tokens", async function () { + const { + josh, + balancerREthStrategy, + timelock, + weth, + reth, + oethHarvester, + rEthBPT, + oethDripper, + } = fixture; + + await balancerREthStrategy + .connect(timelock) + .setMaxDepositSlippage(parseUnits("1", 16)); // 1% + + await depositTest(fixture, [5, 5], [weth, reth], rEthBPT); + await mineBlocks(1000); + const wethBalanceBefore = await weth.balanceOf(oethDripper.address); await oethHarvester.connect(josh)[ // eslint-disable-next-line "harvestAndSwap(address)" ](balancerREthStrategy.address); + + const wethBalanceDiff = wethBalanceBefore.sub( + await weth.balanceOf(oethDripper.address) + ); + + expect(wethBalanceDiff).to.be.gte(oethUnits("0")); }); }); } From 5a338d69f7f4048bfbed2dcc0c4d7647f7c29432 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 12:43:18 +0200 Subject: [PATCH 53/67] fix bad merge + prettier & lint --- .../balancer/BalancerMetaPoolStrategy.sol | 4 +++- .../balancer/BaseBalancerStrategy.sol | 14 +++++------ .../balancerMetaStablePool.fork-test.js | 24 +++++++++---------- .../balancerPoolReentrancy.fork-test.js | 2 +- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 99af48170e..6c752544c2 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -398,7 +398,9 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address(this) ); // Get the balancer pool assets and their total balances - (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens(balancerPoolId); + (IERC20[] memory tokens, , ) = balancerVault.getPoolTokens( + balancerPoolId + ); uint256[] memory minAmountsOut = new uint256[](tokens.length); address[] memory poolAssets = new address[](tokens.length); for (uint256 i = 0; i < tokens.length; ++i) { diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index e965cdd5a9..82639a62ee 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -265,20 +265,18 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { returns (uint256 bptExpected) { uint256 bptRate = IRateProvider(platformAddress).getRate(); - uint256 poolAssetRate = getRateProviderRate(_asset); + uint256 poolAssetRate = _getRateProviderRate(_asset); bptExpected = _amount.mulTruncate(poolAssetRate).divPrecisely(bptRate); } - function _getBPTExpected(address[] memory _assets, uint256[] memory _amounts) - internal - view - virtual - returns (uint256 bptExpected) - { + function _getBPTExpected( + address[] memory _assets, + uint256[] memory _amounts + ) internal view virtual returns (uint256 bptExpected) { require(_assets.length == _amounts.length, "Assets & amounts mismatch"); for (uint256 i = 0; i < _assets.length; ++i) { - uint256 poolAssetRate = getRateProviderRate(_assets[i]); + uint256 poolAssetRate = _getRateProviderRate(_assets[i]); // convert asset amount to ETH amount bptExpected += _amounts[i].mulTruncate(poolAssetRate); } diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index aa6b7131dd..b8569a3a76 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -1,6 +1,6 @@ const { expect } = require("chai"); const { formatUnits } = require("ethers").utils; -const { BigNumber } = require("ethers"); +const { BigNumber, utils } = require("ethers"); const addresses = require("../../utils/addresses"); const { balancer_rETH_WETH_PID } = require("../../utils/constants"); @@ -43,7 +43,7 @@ forkOnlyDescribe( let fixture; - describe("Post deployment", () => { + describe.only("Post deployment", () => { beforeEach(async () => { fixture = await loadBalancerREthFixtureDefault(); }); @@ -178,7 +178,7 @@ forkOnlyDescribe( }); }); - describe("Deposit", function () { + describe.only("Deposit", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureNotDefault(); }); @@ -256,7 +256,7 @@ forkOnlyDescribe( }); }); - describe("Withdraw", function () { + describe.only("Withdraw", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureNotDefault(); const { balancerREthStrategy, oethVault, strategist, reth, weth } = @@ -354,7 +354,7 @@ forkOnlyDescribe( it("Should be able to withdraw with higher withdrawal deviation", async function () {}); }); - describe("Large withdraw", function () { + describe.only("Large withdraw", function () { const depositAmount = 30000; let depositAmountUnits, oethVaultSigner; beforeEach(async () => { @@ -557,7 +557,7 @@ forkOnlyDescribe( }); }); - describe("Harvest rewards", function () { + describe.only("Harvest rewards", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureDefault(); }); @@ -586,7 +586,7 @@ forkOnlyDescribe( await balancerREthStrategy .connect(timelock) - .setMaxDepositSlippage(parseUnits("1", 16)); // 1% + .setMaxDepositSlippage(utils.parseUnits("1", 16)); // 1% await depositTest(fixture, [5, 5], [weth, reth], rEthBPT); await mineBlocks(1000); @@ -615,7 +615,7 @@ forkOnlyDescribe( await balancerREthStrategy .connect(timelock) - .setMaxDepositSlippage(parseUnits("1", 16)); // 1% + .setMaxDepositSlippage(utils.parseUnits("1", 16)); // 1% await depositTest(fixture, [5, 5], [weth, reth], rEthBPT); await mineBlocks(1000); @@ -639,7 +639,7 @@ forkOnlyDescribe( forkOnlyDescribe( "ForkTest: Balancer MetaStablePool wstETH/WETH Strategy", function () { - describe("Deposit", function () { + describe.only("Deposit", function () { let fixture; beforeEach(async () => { @@ -679,7 +679,7 @@ forkOnlyDescribe( }); }); - describe("Withdraw", function () { + describe.only("Withdraw", function () { let fixture; beforeEach(async () => { @@ -777,7 +777,7 @@ forkOnlyDescribe( }); }); - describe("Harvest rewards", function () { + describe.only("Harvest rewards", function () { it("Should be able to collect reward tokens", async function () { const { josh, balancerWstEthStrategy, oethHarvester } = await loadBalancerWstEthFixture(); @@ -789,7 +789,7 @@ forkOnlyDescribe( }); }); - describe("work in MEV environment", function () { + describe.only("work in MEV environment", function () { let attackerAddress; let sAttacker; let fixture; diff --git a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js index b97c775334..5bec3b2452 100644 --- a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js +++ b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js @@ -29,7 +29,7 @@ forkOnlyDescribe( fixture = await loadFixture(); }); - it("Should not allow read-only reentrancy", async () => { + it.only("Should not allow read-only reentrancy", async () => { const { weth, reth, oethVault, rEthBPT, balancerREthPID, daniel } = fixture; From d2c0039b647e77a3e366c919fe8c126153e057a2 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 12:56:16 +0200 Subject: [PATCH 54/67] fix fork tests remove .only --- .../test/strategies/balancerMetaStablePool.fork-test.js | 8 -------- .../test/strategies/balancerPoolReentrancy.fork-test.js | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index b8569a3a76..558b91ac34 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -584,10 +584,6 @@ forkOnlyDescribe( oethUnits("0") ); - await balancerREthStrategy - .connect(timelock) - .setMaxDepositSlippage(utils.parseUnits("1", 16)); // 1% - await depositTest(fixture, [5, 5], [weth, reth], rEthBPT); await mineBlocks(1000); @@ -613,10 +609,6 @@ forkOnlyDescribe( oethDripper, } = fixture; - await balancerREthStrategy - .connect(timelock) - .setMaxDepositSlippage(utils.parseUnits("1", 16)); // 1% - await depositTest(fixture, [5, 5], [weth, reth], rEthBPT); await mineBlocks(1000); diff --git a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js index 5bec3b2452..b97c775334 100644 --- a/contracts/test/strategies/balancerPoolReentrancy.fork-test.js +++ b/contracts/test/strategies/balancerPoolReentrancy.fork-test.js @@ -29,7 +29,7 @@ forkOnlyDescribe( fixture = await loadFixture(); }); - it.only("Should not allow read-only reentrancy", async () => { + it("Should not allow read-only reentrancy", async () => { const { weth, reth, oethVault, rEthBPT, balancerREthPID, daniel } = fixture; From 70b448142395a52874451bf6ef7fc6790e6ee00f Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 12:56:27 +0200 Subject: [PATCH 55/67] remove only --- .../balancerMetaStablePool.fork-test.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 558b91ac34..06041b070d 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -43,7 +43,7 @@ forkOnlyDescribe( let fixture; - describe.only("Post deployment", () => { + describe("Post deployment", () => { beforeEach(async () => { fixture = await loadBalancerREthFixtureDefault(); }); @@ -178,7 +178,7 @@ forkOnlyDescribe( }); }); - describe.only("Deposit", function () { + describe("Deposit", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureNotDefault(); }); @@ -256,7 +256,7 @@ forkOnlyDescribe( }); }); - describe.only("Withdraw", function () { + describe("Withdraw", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureNotDefault(); const { balancerREthStrategy, oethVault, strategist, reth, weth } = @@ -354,7 +354,7 @@ forkOnlyDescribe( it("Should be able to withdraw with higher withdrawal deviation", async function () {}); }); - describe.only("Large withdraw", function () { + describe("Large withdraw", function () { const depositAmount = 30000; let depositAmountUnits, oethVaultSigner; beforeEach(async () => { @@ -557,7 +557,7 @@ forkOnlyDescribe( }); }); - describe.only("Harvest rewards", function () { + describe("Harvest rewards", function () { beforeEach(async () => { fixture = await loadBalancerREthFixtureDefault(); }); @@ -631,7 +631,7 @@ forkOnlyDescribe( forkOnlyDescribe( "ForkTest: Balancer MetaStablePool wstETH/WETH Strategy", function () { - describe.only("Deposit", function () { + describe("Deposit", function () { let fixture; beforeEach(async () => { @@ -671,7 +671,7 @@ forkOnlyDescribe( }); }); - describe.only("Withdraw", function () { + describe("Withdraw", function () { let fixture; beforeEach(async () => { @@ -769,7 +769,7 @@ forkOnlyDescribe( }); }); - describe.only("Harvest rewards", function () { + describe("Harvest rewards", function () { it("Should be able to collect reward tokens", async function () { const { josh, balancerWstEthStrategy, oethHarvester } = await loadBalancerWstEthFixture(); @@ -781,7 +781,7 @@ forkOnlyDescribe( }); }); - describe.only("work in MEV environment", function () { + describe("work in MEV environment", function () { let attackerAddress; let sAttacker; let fixture; From 900e6d0d8edb5c7bd4c402055dc40562ea82943c Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 13:12:21 +0200 Subject: [PATCH 56/67] lint --- contracts/test/strategies/balancerMetaStablePool.fork-test.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 06041b070d..0317e1528e 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -1,6 +1,6 @@ const { expect } = require("chai"); const { formatUnits } = require("ethers").utils; -const { BigNumber, utils } = require("ethers"); +const { BigNumber } = require("ethers"); const addresses = require("../../utils/addresses"); const { balancer_rETH_WETH_PID } = require("../../utils/constants"); @@ -565,7 +565,6 @@ forkOnlyDescribe( it("Should be able to collect reward tokens", async function () { const { weth, - timelock, reth, rEthBPT, balancerREthStrategy, @@ -601,7 +600,6 @@ forkOnlyDescribe( const { josh, balancerREthStrategy, - timelock, weth, reth, oethHarvester, From 38a7e86deebde4e16774321eba064bbb2a1e56c2 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 13:17:28 +0200 Subject: [PATCH 57/67] fix unit tests --- contracts/test/_fixture.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 2badc0c899..6f83c578d8 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -83,10 +83,7 @@ const defaultFixture = deployments.createFixture(async () => { const ousd = await ethers.getContractAt("OUSD", ousdProxy.address); const vault = await ethers.getContractAt("IVault", vaultProxy.address); - const vaultValueChecker = await ethers.getContract("VaultValueChecker"); - const oethVaultValueChecker = await ethers.getContract( - "OETHVaultValueChecker" - ); + const oethProxy = await ethers.getContract("OETHProxy"); const OETHVaultProxy = await ethers.getContract("OETHVaultProxy"); const oethVault = await ethers.getContractAt( @@ -227,7 +224,9 @@ const defaultFixture = deployments.createFixture(async () => { mock1InchSwapRouter, ConvexEthMetaStrategyProxy, ConvexEthMetaStrategy, - fluxStrategy; + fluxStrategy, + vaultValueChecker, + oethVaultValueChecker; if (isFork) { usdt = await ethers.getContractAt(usdtAbi, addresses.mainnet.USDT); @@ -370,6 +369,12 @@ const defaultFixture = deployments.createFixture(async () => { "CompoundStrategy", fluxStrategyProxy.address ); + + vaultValueChecker = await ethers.getContract("VaultValueChecker"); + oethVaultValueChecker = await ethers.getContract( + "OETHVaultValueChecker" + ); + } else { usdt = await ethers.getContract("MockUSDT"); dai = await ethers.getContract("MockDAI"); From 3fd8f23efb1cb80041f2c373ee6f2c74e5523734 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 13:57:22 +0200 Subject: [PATCH 58/67] add more tests to see how checkBalance behaves --- contracts/test/_fixture.js | 7 +- .../balancerMetaStablePool.fork-test.js | 89 +++++++++++++------ 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 6f83c578d8..19df0bb5e6 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -83,7 +83,7 @@ const defaultFixture = deployments.createFixture(async () => { const ousd = await ethers.getContractAt("OUSD", ousdProxy.address); const vault = await ethers.getContractAt("IVault", vaultProxy.address); - + const oethProxy = await ethers.getContract("OETHProxy"); const OETHVaultProxy = await ethers.getContract("OETHVaultProxy"); const oethVault = await ethers.getContractAt( @@ -371,10 +371,7 @@ const defaultFixture = deployments.createFixture(async () => { ); vaultValueChecker = await ethers.getContract("VaultValueChecker"); - oethVaultValueChecker = await ethers.getContract( - "OETHVaultValueChecker" - ); - + oethVaultValueChecker = await ethers.getContract("OETHVaultValueChecker"); } else { usdt = await ethers.getContract("MockUSDT"); dai = await ethers.getContract("MockDAI"); diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 0317e1528e..a256f4e775 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -985,38 +985,69 @@ forkOnlyDescribe( expect(profitDiff).to.be.lte(oethUnits("-0.5"), 1); }); - it("checkBalance with ~100 units should almost not be affected by heavy pool manipulation", async function () { - const { balancerREthStrategy, weth, reth, rEthBPT, balancerVault } = - fixture; + // consists of test cases with variable tilt percentage and expected balance diff + const checkBalanceTestCases = [ + /* +100% tilt & 0.012 expected change means: + * - pool has been tilted using WETH deposit that equals 100% of pools current + * liquidity. Meaning if pool has 10k WETH & 10k RETH the tilt action will be + * depositing additional 20k WETH totaling pool to: 30k WETH & 10k RETH + * - 0.012 expected change means 0.012 diff between pre-tilt checkBalance and after + * tilt checkBalance call. Strategy has roughly ~100 units deposited so 0.012 + * change would equal 0.012/100 = 0.00012 change if 1 is a whole. Or 0.012% + */ + [100, "0.012"], + [200, "0.016"], + [300, "0.018"], + [400, "0.02"], + [500, "0.02"], + ]; - await depositTest(fixture, [50, 50], [weth, reth], rEthBPT); + for (const testCase of checkBalanceTestCases) { + const tiltAmount = testCase[0]; + const maxDiff = testCase[1]; + + it(`checkBalance with ~100 units should at most have ${maxDiff} absolute diff when performing WETH pool tilt at ${tiltAmount}% of pool's TVL`, async function () { + const { balancerREthStrategy, weth, reth, rEthBPT, balancerVault } = + fixture; + + await depositTest(fixture, [50, 50], [weth, reth], rEthBPT); + + const checkBalanceAmount = await balancerREthStrategy[ + "checkBalance()" + ](); + expect(checkBalanceAmount).to.be.gte(oethUnits("0"), 1); + + await tiltBalancerMetaStableWETHPool({ + percentageOfTVLDeposit: tiltAmount, + attackerSigner: sAttacker, + balancerPoolId: await balancerREthStrategy.balancerPoolId(), + assetAddressArray: [reth.address, weth.address], + wethIndex: 1, + bptToken: rEthBPT, + balancerVault, + reth, + weth, + }); + + const checkBalanceAmountAfterTilt = await balancerREthStrategy[ + "checkBalance()" + ](); + expect(checkBalanceAmountAfterTilt).to.be.gte( + await oethUnits("0"), + 1 + ); - const checkBalanceAmount = await balancerREthStrategy[ - "checkBalance()" - ](); - expect(checkBalanceAmount).to.be.gte(oethUnits("0"), 1); - - await tiltBalancerMetaStableWETHPool({ - percentageOfTVLDeposit: 300, // 300% - attackerSigner: sAttacker, - balancerPoolId: await balancerREthStrategy.balancerPoolId(), - assetAddressArray: [reth.address, weth.address], - wethIndex: 1, - bptToken: rEthBPT, - balancerVault, - reth, - weth, + const checkBalanceDiff = + checkBalanceAmountAfterTilt.sub(checkBalanceAmount); + console.log( + `diff ${maxDiff} tilt ${tiltAmount} actual diff: ${ + parseFloat(checkBalanceDiff.toString()) / 1e18 + }` + ); + // ~100 units in pool liquidity should have less than 0.02 effect == 0.02% + expect(checkBalanceDiff).to.be.lte(oethUnits(maxDiff)); }); - - const checkBalanceAmountAfterTilt = await balancerREthStrategy[ - "checkBalance()" - ](); - expect(checkBalanceAmountAfterTilt).to.be.gte(await oethUnits("0"), 1); - // ~100 units in pool liquidity should have less than 0.02 effect == 0.02% - expect(checkBalanceAmountAfterTilt.sub(checkBalanceAmount)).to.be.lte( - oethUnits("0.02") - ); - }); + } }); } ); From 88bfd3015a266502547904e7cd6c3dd74f49e301 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 14:01:47 +0200 Subject: [PATCH 59/67] remove console log --- .../test/strategies/balancerMetaStablePool.fork-test.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index a256f4e775..533f92225b 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -1039,11 +1039,6 @@ forkOnlyDescribe( const checkBalanceDiff = checkBalanceAmountAfterTilt.sub(checkBalanceAmount); - console.log( - `diff ${maxDiff} tilt ${tiltAmount} actual diff: ${ - parseFloat(checkBalanceDiff.toString()) / 1e18 - }` - ); // ~100 units in pool liquidity should have less than 0.02 effect == 0.02% expect(checkBalanceDiff).to.be.lte(oethUnits(maxDiff)); }); From b7e0dc3e568357d8d0c3fabb003a6db0e9ada722 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 31 Aug 2023 17:04:13 +0200 Subject: [PATCH 60/67] improve checkBalance test by testing that checkBalance amount doesn't decrease after the attack comaring to the middle of the attack. --- contracts/test/_fixture.js | 50 +++++++++++++++++++ .../balancerMetaStablePool.fork-test.js | 19 ++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 19df0bb5e6..edb0b1dab7 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -991,6 +991,55 @@ async function tiltBalancerMetaStableWETHPool({ ); } +/* Withdraw WETH liquidity in Balancer metaStable WETH pool to simulate + * second part of the MEV attack. All attacker WETH liquidity is withdrawn. + */ +async function untiltBalancerMetaStableWETHPool({ + attackerSigner, + balancerPoolId, + assetAddressArray, + wethIndex, + bptToken, + balancerVault, +}) { + const amountsOut = Array(assetAddressArray.length).fill(BigNumber.from("0")); + + /* encode user data for pool joining + * + * EXACT_BPT_IN_FOR_ONE_TOKEN_OUT: + * User sends a precise quantity of BPT, and receives an estimated + * but unknown (computed at run time) quantity of a single token + * + * ['uint256', 'uint256', 'uint256'] + * [EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, bptAmountIn, exitTokenIndex] + */ + const userData = ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256", "uint256"], + [ + 0, + await bptToken.balanceOf(attackerSigner.address), + BigNumber.from(wethIndex.toString()), + ] + ); + + await bptToken + .connect(attackerSigner) + .approve(balancerVault.address, oethUnits("1").mul(oethUnits("1"))); // 1e36 + + await balancerVault.connect(attackerSigner).exitPool( + balancerPoolId, // poolId + attackerSigner.address, // sender + attackerSigner.address, // recipient + [ + //ExitPoolRequest + assetAddressArray, // assets + amountsOut, // minAmountsOut + userData, // userData + false, // fromInternalBalance + ] + ); +} + /** * Configure a Vault with the balancerREthStrategy */ @@ -2058,6 +2107,7 @@ module.exports = { balancerREthFixture, balancerWstEthFixture, tiltBalancerMetaStableWETHPool, + untiltBalancerMetaStableWETHPool, fraxETHStrategyFixture, oethMorphoAaveFixture, mintWETH, diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index 533f92225b..a9637da47d 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -13,6 +13,7 @@ const { mineBlocks, mintWETH, tiltBalancerMetaStableWETHPool, + untiltBalancerMetaStableWETHPool, } = require("../_fixture"); const temporaryFork = require("../../utils/temporaryFork"); @@ -1017,10 +1018,11 @@ forkOnlyDescribe( ](); expect(checkBalanceAmount).to.be.gte(oethUnits("0"), 1); + const poolId = await balancerREthStrategy.balancerPoolId(); await tiltBalancerMetaStableWETHPool({ percentageOfTVLDeposit: tiltAmount, attackerSigner: sAttacker, - balancerPoolId: await balancerREthStrategy.balancerPoolId(), + balancerPoolId: poolId, assetAddressArray: [reth.address, weth.address], wethIndex: 1, bptToken: rEthBPT, @@ -1041,6 +1043,21 @@ forkOnlyDescribe( checkBalanceAmountAfterTilt.sub(checkBalanceAmount); // ~100 units in pool liquidity should have less than 0.02 effect == 0.02% expect(checkBalanceDiff).to.be.lte(oethUnits(maxDiff)); + + await untiltBalancerMetaStableWETHPool({ + attackerSigner: sAttacker, + balancerPoolId: poolId, + assetAddressArray: [reth.address, weth.address], + wethIndex: 1, + bptToken: rEthBPT, + balancerVault, + }); + + // check balance should report an equal or larger balance after attack comparing + // to the middle of the attack. + expect(checkBalanceAmountAfterTilt).to.be.gte( + checkBalanceAmountAfterTilt + ); }); } }); From a0cb91983ccd48d6e95062b25329a1ee62d00fdc Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 7 Sep 2023 01:24:42 +0200 Subject: [PATCH 61/67] confirm that yield gained by 3rd party tilting the pool can be extracted by withdrawing the funds --- contracts/contracts/interfaces/IRETH.sol | 2 + .../balancerMetaStablePool.fork-test.js | 66 +++++++++++++++++-- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/contracts/contracts/interfaces/IRETH.sol b/contracts/contracts/interfaces/IRETH.sol index c4fe5db32d..ea70d6e516 100644 --- a/contracts/contracts/interfaces/IRETH.sol +++ b/contracts/contracts/interfaces/IRETH.sol @@ -6,6 +6,8 @@ interface IRETH { function getRethValue(uint256 _ethAmount) external view returns (uint256); + function getExchangeRate() external view returns (uint256); + function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); diff --git a/contracts/test/strategies/balancerMetaStablePool.fork-test.js b/contracts/test/strategies/balancerMetaStablePool.fork-test.js index a9637da47d..192743c448 100644 --- a/contracts/test/strategies/balancerMetaStablePool.fork-test.js +++ b/contracts/test/strategies/balancerMetaStablePool.fork-test.js @@ -1008,8 +1008,29 @@ forkOnlyDescribe( const maxDiff = testCase[1]; it(`checkBalance with ~100 units should at most have ${maxDiff} absolute diff when performing WETH pool tilt at ${tiltAmount}% of pool's TVL`, async function () { - const { balancerREthStrategy, weth, reth, rEthBPT, balancerVault } = - fixture; + const { + oeth, + oethVault, + balancerREthPID, + balancerREthStrategy, + weth, + reth, + rEthBPT, + balancerVault, + } = fixture; + + const logParams = { + oeth, + oethVault, + bpt: rEthBPT, + balancerVault, + strategy: balancerREthStrategy, + allAssets: [weth, reth], + pid: balancerREthPID, + reth, + }; + + const balancesBefore = await logBalances(logParams); await depositTest(fixture, [50, 50], [weth, reth], rEthBPT); @@ -1053,11 +1074,38 @@ forkOnlyDescribe( balancerVault, }); - // check balance should report an equal or larger balance after attack comparing - // to the middle of the attack. - expect(checkBalanceAmountAfterTilt).to.be.gte( + const checkBalanceAmountAfterAttack = await balancerREthStrategy[ + "checkBalance()" + ](); + + // check balance should report larger balance after attack comparing + // to the middle of the attack. Since the attacker has encountered + // fees with un-tilting. + expect(checkBalanceAmountAfterAttack).to.be.gt( checkBalanceAmountAfterTilt ); + + const oethVaultSigner = await impersonateAndFundContract( + oethVault.address + ); + await balancerREthStrategy.connect(oethVaultSigner).withdrawAll(); + + const balancesAfter = await logBalances(logParams); + + const rethDiff = + parseFloat(balancesAfter.vaultAssets.rETH.toString()) - + parseFloat(balancesBefore.vaultAssets.rETH.toString()); + const wethDiff = + parseFloat(balancesAfter.vaultAssets.WETH.toString()) - + parseFloat(balancesBefore.vaultAssets.WETH.toString()); + const rethExchangeRate = + parseFloat(await reth.getExchangeRate()) / 1e18; + const unitDiff = rethDiff * rethExchangeRate + wethDiff; + + /* confirm that the profits gained by the attacker's pool tilt + * action can be extracted by withdrawing the funds. + */ + expect(unitDiff / 1e18).to.be.gte(parseFloat(maxDiff)); }); } }); @@ -1234,9 +1282,12 @@ async function logBalances({ log(`\nOETH total supply: ${formatUnits(oethSupply)}`); log(`BPT total supply : ${formatUnits(bptSupply)}`); + const vaultAssets = {}; for (const asset of allAssets) { - const vaultAssets = await asset.balanceOf(oethVault.address); - log(`${await asset.symbol()} in vault ${formatUnits(vaultAssets)}`); + const vaultAssetAmount = await asset.balanceOf(oethVault.address); + const symbol = await asset.symbol(); + log(`${symbol} in vault ${formatUnits(vaultAssetAmount)}`); + vaultAssets[symbol] = vaultAssetAmount; } const strategyValues = await getPoolValues(strategy, allAssets, reth); @@ -1248,5 +1299,6 @@ async function logBalances({ bptSupply, strategyValues, poolBalances, + vaultAssets, }; } From 0f02fada0152d2da13af2969edf9e05056cdd01b Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 11 Sep 2023 17:38:01 +0200 Subject: [PATCH 62/67] rename internal functions by prepending them with underscore --- contracts/contracts/proxies/Proxies.sol | 1 - .../balancer/BalancerMetaPoolStrategy.sol | 16 ++++++++-------- .../strategies/balancer/BaseBalancerStrategy.sol | 16 ++++++++-------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/contracts/contracts/proxies/Proxies.sol b/contracts/contracts/proxies/Proxies.sol index d08b7658e1..ad1bb9078b 100644 --- a/contracts/contracts/proxies/Proxies.sol +++ b/contracts/contracts/proxies/Proxies.sol @@ -158,7 +158,6 @@ contract OETHMorphoAaveStrategyProxy is InitializeGovernedUpgradeabilityProxy { } /** -<<<<<<< HEAD * @notice OETHBalancerMetaPoolrEthStrategyProxy delegates calls to a BalancerMetaPoolStrategy implementation */ contract OETHBalancerMetaPoolrEthStrategyProxy is diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index 6c752544c2..b45241cbfc 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -108,13 +108,13 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { assetToPToken[strategyAsset] != address(0), "Unsupported asset" ); - strategyAssetsToPoolAssets[i] = toPoolAsset(strategyAsset); + strategyAssetsToPoolAssets[i] = _toPoolAsset(strategyAsset); if (strategyAmount > 0) { emit Deposit(strategyAsset, platformAddress, strategyAmount); // wrap rebasing assets like stETH and frxETH to wstETH and sfrxETH - (, strategyAssetAmountsToPoolAssetAmounts[i]) = wrapPoolAsset( + (, strategyAssetAmountsToPoolAssetAmounts[i]) = _wrapPoolAsset( strategyAsset, strategyAmount ); @@ -254,13 +254,13 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { poolAssets[i] = address(tokens[i]); // Convert the Balancer pool asset back to a vault collateral asset - address strategyAsset = fromPoolAsset(poolAssets[i]); + address strategyAsset = _fromPoolAsset(poolAssets[i]); // for each of the vault assets for (uint256 j = 0; j < _strategyAssets.length; ++j) { // If the vault asset equals the vault asset mapped from the Balancer pool asset if (_strategyAssets[j] == strategyAsset) { - (, poolAssetsAmountsOut[i]) = toPoolAsset( + (, poolAssetsAmountsOut[i]) = _toPoolAsset( strategyAsset, _strategyAmounts[j] ); @@ -361,7 +361,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { for (uint256 i = 0; i < _strategyAssets.length; ++i) { // Unwrap assets like wstETH and sfrxETH to rebasing assets stETH and frxETH if (strategyAssetsToPoolAssetsAmounts[i] > 0) { - unwrapPoolAsset( + _unwrapPoolAsset( _strategyAssets[i], strategyAssetsToPoolAssetsAmounts[i] ); @@ -442,7 +442,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { for (uint256 i = 0; i < tokens.length; ++i) { address poolAsset = address(tokens[i]); // Convert the balancer pool asset to the strategy asset - address strategyAsset = fromPoolAsset(poolAsset); + address strategyAsset = _fromPoolAsset(poolAsset); // Get the balancer pool assets withdraw from the pool plus any that were already in this strategy contract uint256 poolAssetAmount = IERC20(poolAsset).balanceOf( address(this) @@ -451,7 +451,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { // Unwrap assets like wstETH and sfrxETH to rebasing assets stETH and frxETH uint256 unwrappedAmount = 0; if (poolAssetAmount > 0) { - unwrappedAmount = unwrapPoolAsset( + unwrappedAmount = _unwrapPoolAsset( strategyAsset, poolAssetAmount ); @@ -500,7 +500,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { // solhint-disable-next-line no-unused-vars function _abstractSetPToken(address _asset, address) internal override { - address poolAsset = toPoolAsset(_asset); + address poolAsset = _toPoolAsset(_asset); if (_asset == stETH) { // slither-disable-next-line unused-return IERC20(stETH).approve(wstETH, type(uint256).max); diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index 82639a62ee..f046c2fb82 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -111,7 +111,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { "Pool assets length mismatch" ); for (uint256 i = 0; i < _assets.length; ++i) { - address asset = fromPoolAsset(address(poolAssets[i])); + address asset = _fromPoolAsset(address(poolAssets[i])); require(_assets[i] == asset, "Pool assets mismatch"); } @@ -184,7 +184,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * Because this function returns the balance of the asset and is not denominated in * ETH units we need to convert the ETH denominated amount to asset amount. */ - if (toPoolAsset(_asset) == _asset) { + if (_toPoolAsset(_asset) == _asset) { amount = amount.divPrecisely(_getRateProviderRate(_asset)); } } @@ -305,7 +305,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * that the strategy supports. This function converts the pool(wrapped) asset * and corresponding amount to strategy asset. */ - function toPoolAsset(address asset, uint256 amount) + function _toPoolAsset(address asset, uint256 amount) internal view returns (address poolAsset, uint256 poolAmount) @@ -332,7 +332,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * @param asset Address of the Vault collateral asset. * @return Address of the Balancer pool asset. */ - function toPoolAsset(address asset) internal view returns (address) { + function _toPoolAsset(address asset) internal view returns (address) { if (asset == stETH) { return wstETH; } else if (asset == frxETH) { @@ -344,7 +344,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { /** * @dev Converts rebasing asset to its wrapped counterpart. */ - function wrapPoolAsset(address asset, uint256 amount) + function _wrapPoolAsset(address asset, uint256 amount) internal returns (address wrappedAsset, uint256 wrappedAmount) { @@ -370,7 +370,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { /** * @dev Converts wrapped asset to its rebasing counterpart. */ - function unwrapPoolAsset(address asset, uint256 amount) + function _unwrapPoolAsset(address asset, uint256 amount) internal returns (uint256 unwrappedAmount) { @@ -392,7 +392,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { * that the strategy supports. This function converts the rebasing strategy asset * and corresponding amount to wrapped(pool) asset. */ - function fromPoolAsset(address poolAsset, uint256 poolAmount) + function _fromPoolAsset(address poolAsset, uint256 poolAmount) internal view returns (address asset, uint256 amount) @@ -413,7 +413,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { } } - function fromPoolAsset(address poolAsset) + function _fromPoolAsset(address poolAsset) internal view returns (address asset) From 3019b49661ce15c533541a301d6ed8c310d20ce2 Mon Sep 17 00:00:00 2001 From: Nick Addison Date: Tue, 12 Sep 2023 07:11:20 +1000 Subject: [PATCH 63/67] Generated latest Balancer strategy diagrams (#1805) --- .../BalancerMetaPoolStrategyHierarchy.svg | 508 +++++++++--------- .../docs/BalancerMetaPoolStrategySquashed.svg | 52 +- .../docs/BalancerMetaPoolStrategyStorage.svg | 380 ++++--------- contracts/docs/generate.sh | 2 +- 4 files changed, 389 insertions(+), 553 deletions(-) diff --git a/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg b/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg index 81aab10525..612635255c 100644 --- a/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg +++ b/contracts/docs/BalancerMetaPoolStrategyHierarchy.svg @@ -4,338 +4,318 @@ - + UmlClassDiagram - + 7 - -Governable -../contracts/governance/Governable.sol + +Governable +../contracts/governance/Governable.sol - + -35 - -<<Interface>> -IOracle -../contracts/interfaces/IOracle.sol +41 + +<<Interface>> +IVault +../contracts/interfaces/IVault.sol - - -42 - -<<Interface>> -IVault -../contracts/interfaces/IVault.sol - - - -184 - -VaultStorage -../contracts/vault/VaultStorage.sol + + +186 + +VaultStorage +../contracts/vault/VaultStorage.sol - + -42->184 - - +41->186 + + - + + +43 + +<<Interface>> +IWstETH +../contracts/interfaces/IWstETH.sol + + -44 - -<<Interface>> -IWstETH -../contracts/interfaces/IWstETH.sol +193 + +<<Interface>> +IBalancerVault +../contracts/interfaces/balancer/IBalancerVault.sol - + -191 - -<<Interface>> -IBalancerVault -../contracts/interfaces/balancer/IBalancerVault.sol +200 + +<<Interface>> +IMetaStablePool +../contracts/interfaces/balancer/IMetaStablePool.sol - + -198 - -<<Interface>> -IMetaStablePool -../contracts/interfaces/balancer/IMetaStablePool.sol - - - -199 - -<<Interface>> -IRateProvider -../contracts/interfaces/balancer/IRateProvider.sol +201 + +<<Interface>> +IRateProvider +../contracts/interfaces/balancer/IRateProvider.sol - + -198->199 - - +200->201 + + - - -152 - -<<Interface>> -IRewardStaking -../contracts/strategies/IRewardStaking.sol + + +154 + +<<Interface>> +IRewardStaking +../contracts/strategies/IRewardStaking.sol - - -231 - -BalancerMetaPoolStrategy -../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol + + +233 + +BalancerMetaPoolStrategy +../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol - + -231->191 - - +233->193 + + - + -231->198 - - +233->200 + + - + -231->199 - - +233->201 + + - - -232 - -<<Abstract>> -BaseAuraStrategy -../contracts/strategies/balancer/BaseAuraStrategy.sol + + +234 + +<<Abstract>> +BaseAuraStrategy +../contracts/strategies/balancer/BaseAuraStrategy.sol - + -231->232 - - +233->234 + + - + -232->152 - - +234->154 + + - - -233 - -<<Abstract>> -BaseBalancerStrategy -../contracts/strategies/balancer/BaseBalancerStrategy.sol + + +235 + +<<Abstract>> +BaseBalancerStrategy +../contracts/strategies/balancer/BaseBalancerStrategy.sol - + -232->233 - - +234->235 + + - - -236 - -<<Interface>> -IERC4626 -../lib/openzeppelin/interfaces/IERC4626.sol + + +238 + +<<Interface>> +IERC4626 +../lib/openzeppelin/interfaces/IERC4626.sol - + -232->236 - - - - - -233->35 - - +234->238 + + - + -233->42 - - +235->43 + + - - -233->44 - - - - + -233->191 - - +235->193 + + - + -233->199 - - +235->201 + + - - -172 - -<<Abstract>> -InitializableAbstractStrategy -../contracts/utils/InitializableAbstractStrategy.sol + + +174 + +<<Abstract>> +InitializableAbstractStrategy +../contracts/utils/InitializableAbstractStrategy.sol - + -233->172 - - +235->174 + + - - -163 - -OUSD -../contracts/token/OUSD.sol + + +165 + +OUSD +../contracts/token/OUSD.sol - - -163->7 - - + + +165->7 + + - - -171 - -<<Abstract>> -Initializable -../contracts/utils/Initializable.sol + + +173 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol - - -163->171 - - + + +165->173 + + - - -174 - -<<Abstract>> -InitializableERC20Detailed -../contracts/utils/InitializableERC20Detailed.sol + + +176 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol - - -163->174 - - + + +165->176 + + - - -172->7 - - + + +174->7 + + - - -172->42 - - + + +174->41 + + + + + +174->173 + + - + -172->171 - - +174->174 + + - - -172->172 - - + + +362 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - - -360 - -<<Interface>> -IERC20 -../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + +174->362 + + - + -172->360 - - +176->362 + + - + -174->360 - - +186->7 + + - + + +186->165 + + + + + +186->173 + + + + -184->7 - - +238->362 + + - - -184->163 - - + + +733 + +<<Interface>> +IERC20Metadata +../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol - - -184->171 - - + + +238->733 + + - + -236->360 - - - - - -731 - -<<Interface>> -IERC20Metadata -../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol - - - -236->731 - - - - - -731->360 - - +733->362 + + diff --git a/contracts/docs/BalancerMetaPoolStrategySquashed.svg b/contracts/docs/BalancerMetaPoolStrategySquashed.svg index 56a39bc216..c8c0ff9b60 100644 --- a/contracts/docs/BalancerMetaPoolStrategySquashed.svg +++ b/contracts/docs/BalancerMetaPoolStrategySquashed.svg @@ -4,18 +4,18 @@ - + UmlClassDiagram - - + + -231 - -BalancerMetaPoolStrategy -../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol - +233 + +BalancerMetaPoolStrategy +../contracts/strategies/balancer/BalancerMetaPoolStrategy.sol + Private:   initialized: bool <<Initializable>>   initializing: bool <<Initializable>> @@ -47,10 +47,10 @@   sfrxETH: address <<BaseBalancerStrategy>>   balancerVault: IBalancerVault <<BaseBalancerStrategy>>   balancerPoolId: bytes32 <<BaseBalancerStrategy>> -   maxWithdrawalSlippage: uint256 <<BaseBalancerStrategy>> -   maxDepositSlippage: uint256 <<BaseBalancerStrategy>> +   maxWithdrawalDeviation: uint256 <<BaseBalancerStrategy>> +   maxDepositDeviation: uint256 <<BaseBalancerStrategy>>   auraRewardPoolAddress: address <<BaseAuraStrategy>> - + Internal:    _governor(): (governorOut: address) <<Governable>>    _pendingGovernor(): (pendingGovernor: address) <<Governable>> @@ -62,12 +62,12 @@    _setPTokenAddress(_asset: address, _pToken: address) <<InitializableAbstractStrategy>>    _abstractSetPToken(_asset: address, address) <<BalancerMetaPoolStrategy>>    _getBalancerPoolTokens(): (balancerPoolTokens: uint256) <<BaseAuraStrategy>> -    getBPTExpected(_asset: address, _amount: uint256): (bptExpected: uint256) <<BaseBalancerStrategy>> -    getBPTExpected(_assets: address[], _amounts: uint256[]): (bptExpected: uint256) <<BaseBalancerStrategy>> +    _getBPTExpected(_asset: address, _amount: uint256): (bptExpected: uint256) <<BaseBalancerStrategy>> +    _getBPTExpected(_assets: address[], _amounts: uint256[]): (bptExpected: uint256) <<BaseBalancerStrategy>>    _lpDepositAll() <<BaseAuraStrategy>>    _lpWithdraw(numBPTTokens: uint256) <<BaseAuraStrategy>>    _lpWithdrawAll() <<BaseAuraStrategy>> -    getPoolAssets(): (assets: IERC20[]) <<BaseBalancerStrategy>> +    _getPoolAssets(): (assets: IERC20[]) <<BaseBalancerStrategy>>    toPoolAsset(asset: address, amount: uint256): (poolAsset: address, poolAmount: uint256) <<BaseBalancerStrategy>>    toPoolAsset(asset: address): address <<BaseBalancerStrategy>>    wrapPoolAsset(asset: address, amount: uint256): (wrappedAsset: address, wrappedAmount: uint256) <<BaseBalancerStrategy>> @@ -75,9 +75,9 @@    fromPoolAsset(poolAsset: address, poolAmount: uint256): (asset: address, amount: uint256) <<BaseBalancerStrategy>>    fromPoolAsset(poolAsset: address): (asset: address) <<BaseBalancerStrategy>>    _approveBase() <<BaseAuraStrategy>> -    getRateProviderRate(_asset: address): uint256 <<BalancerMetaPoolStrategy>> -    _deposit(_assets: address[], _amounts: uint256[]) <<BalancerMetaPoolStrategy>> -    _withdraw(_recipient: address, _assets: address[], _amounts: uint256[]) <<BalancerMetaPoolStrategy>> +    _getRateProviderRate(_asset: address): uint256 <<BalancerMetaPoolStrategy>> +    _deposit(_strategyAssets: address[], _strategyAmounts: uint256[]) <<BalancerMetaPoolStrategy>> +    _withdraw(_recipient: address, _strategyAssets: address[], _strategyAmounts: uint256[]) <<BalancerMetaPoolStrategy>>    _approveAsset(_asset: address) <<BalancerMetaPoolStrategy>> External:    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> @@ -90,17 +90,17 @@    removePToken(_assetIndex: uint256) <<onlyGovernor>> <<InitializableAbstractStrategy>>    setHarvesterAddress(_harvesterAddress: address) <<onlyGovernor>> <<InitializableAbstractStrategy>>    safeApproveAllTokens() <<onlyGovernor, nonReentrant>> <<BalancerMetaPoolStrategy>> -    deposit(_asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    deposit(address, uint256) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>>    depositAll() <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> -    withdraw(_recipient: address, _asset: address, _amount: uint256) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    withdraw(_recipient: address, _strategyAsset: address, _strategyAmount: uint256) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>>    withdrawAll() <<onlyVaultOrGovernor, nonReentrant>> <<BalancerMetaPoolStrategy>>    checkBalance(_asset: address): (amount: uint256) <<whenNotInBalancerVaultContext>> <<BaseBalancerStrategy>>    supportsAsset(_asset: address): bool <<BaseBalancerStrategy>>    checkBalance(): (value: uint256) <<whenNotInBalancerVaultContext>> <<BaseBalancerStrategy>> -    setMaxWithdrawalSlippage(_maxWithdrawalSlippage: uint256) <<onlyVaultOrGovernorOrStrategist>> <<BaseBalancerStrategy>> -    setMaxDepositSlippage(_maxDepositSlippage: uint256) <<onlyVaultOrGovernorOrStrategist>> <<BaseBalancerStrategy>> -    deposit(_assets: address[], _amounts: uint256[]) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> -    withdraw(_recipient: address, _assets: address[], _amounts: uint256[]) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    setMaxWithdrawalDeviation(_maxWithdrawalDeviation: uint256) <<onlyVaultOrGovernorOrStrategist>> <<BaseBalancerStrategy>> +    setMaxDepositDeviation(_maxDepositDeviation: uint256) <<onlyVaultOrGovernorOrStrategist>> <<BaseBalancerStrategy>> +    deposit(address[], uint256[]) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> +    withdraw(_recipient: address, _strategyAssets: address[], _strategyAmounts: uint256[]) <<onlyVault, nonReentrant>> <<BalancerMetaPoolStrategy>> Public:    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>>    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> @@ -111,8 +111,8 @@    <<event>> RewardTokenCollected(recipient: address, rewardToken: address, amount: uint256) <<InitializableAbstractStrategy>>    <<event>> RewardTokenAddressesUpdated(_oldAddresses: address[], _newAddresses: address[]) <<InitializableAbstractStrategy>>    <<event>> HarvesterAddressesUpdated(_oldHarvesterAddress: address, _newHarvesterAddress: address) <<InitializableAbstractStrategy>> -    <<event>> MaxWithdrawalSlippageUpdated(_prevMaxSlippagePercentage: uint256, _newMaxSlippagePercentage: uint256) <<BaseBalancerStrategy>> -    <<event>> MaxDepositSlippageUpdated(_prevMaxSlippagePercentage: uint256, _newMaxSlippagePercentage: uint256) <<BaseBalancerStrategy>> +    <<event>> MaxWithdrawalDeviationUpdated(_prevMaxDeviationPercentage: uint256, _newMaxDeviationPercentage: uint256) <<BaseBalancerStrategy>> +    <<event>> MaxDepositDeviationUpdated(_prevMaxDeviationPercentage: uint256, _newMaxDeviationPercentage: uint256) <<BaseBalancerStrategy>>    <<modifier>> initializer() <<Initializable>>    <<modifier>> onlyGovernor() <<Governable>>    <<modifier>> nonReentrant() <<Governable>> diff --git a/contracts/docs/BalancerMetaPoolStrategyStorage.svg b/contracts/docs/BalancerMetaPoolStrategyStorage.svg index 8d76d6ec64..4d93eb2ddb 100644 --- a/contracts/docs/BalancerMetaPoolStrategyStorage.svg +++ b/contracts/docs/BalancerMetaPoolStrategyStorage.svg @@ -4,282 +4,138 @@ - - + + StorageDiagram - - + + -7 - -BalancerMetaPoolStrategy <<Contract>> - -slot - -0 - -1-50 - -51 - -52 - -53 - -54 - -55 - -56 - -57 - -58 - -59-156 - -157 - -158 - -159-206 - -207-256 - -type: <inherited contract>.variable (bytes) - -unallocated (30) - -bool: Initializable.initializing (1) - -bool: Initializable.initialized (1) - -uint256[50]: Initializable.______gap (1600) - -unallocated (12) - -address: InitializableAbstractStrategy._deprecated_platformAddress (20) - -unallocated (12) - -address: InitializableAbstractStrategy._deprecated_vaultAddress (20) - -mapping(address=>address): InitializableAbstractStrategy.assetToPToken (32) - -address[]: InitializableAbstractStrategy.assetsMapped (32) - -unallocated (12) - -address: InitializableAbstractStrategy._deprecated_rewardTokenAddress (20) - -uint256: InitializableAbstractStrategy._deprecated_rewardLiquidationThreshold (32) - -unallocated (12) - -address: InitializableAbstractStrategy.harvesterAddress (20) - -address[]: InitializableAbstractStrategy.rewardTokenAddresses (32) - -int256[98]: InitializableAbstractStrategy._reserved (3136) - -uint256: BaseBalancerStrategy.maxWithdrawalSlippage (32) - -uint256: BaseBalancerStrategy.maxDepositSlippage (32) - -int256[48]: BaseBalancerStrategy.__reserved (1536) - -int256[50]: BaseAuraStrategy.__reserved_baseAuraStrategy (1600) +3 + +BalancerMetaPoolStrategy <<Contract>> + +slot + +0 + +1-50 + +51 + +52 + +53 + +54 + +55 + +56 + +57 + +58 + +59-156 + +157 + +158 + +159-206 + +207-256 + +type: <inherited contract>.variable (bytes) + +unallocated (30) + +bool: Initializable.initializing (1) + +bool: Initializable.initialized (1) + +uint256[50]: Initializable.______gap (1600) + +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_platformAddress (20) + +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_vaultAddress (20) + +mapping(address=>address): InitializableAbstractStrategy.assetToPToken (32) + +address[]: InitializableAbstractStrategy.assetsMapped (32) + +unallocated (12) + +address: InitializableAbstractStrategy._deprecated_rewardTokenAddress (20) + +uint256: InitializableAbstractStrategy._deprecated_rewardLiquidationThreshold (32) + +unallocated (12) + +address: InitializableAbstractStrategy.harvesterAddress (20) + +address[]: InitializableAbstractStrategy.rewardTokenAddresses (32) + +int256[98]: InitializableAbstractStrategy._reserved (3136) + +uint256: BaseBalancerStrategy.maxWithdrawalDeviation (32) + +uint256: BaseBalancerStrategy.maxDepositDeviation (32) + +int256[48]: BaseBalancerStrategy.__reserved (1536) + +int256[50]: BaseAuraStrategy.__reserved_baseAuraStrategy (1600) 1 - -uint256[50]: ______gap <<Array>> - -slot - -1 - -2 - -3-48 - -49 - -50 - -type: variable (bytes) - -uint256 (32) - -uint256 (32) - ----- (1472) - -uint256 (32) - -uint256 (32) + +address[]: assetsMapped <<Array>> +0x4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b8 + +offset + +0 + +type: variable (bytes) + +unallocated (12) + +address (20) - + -7:8->1 - - +3:8->1 + + 2 - -address[]: assetsMapped <<Array>> -0x4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b8 - -offset - -0 - -type: variable (bytes) - -unallocated (12) - -address (20) + +address[]: rewardTokenAddresses <<Array>> +0xa2999d817b6757290b50e8ecf3fa939673403dd35c97de392fdb343b4015ce9e + +offset + +0 + +type: variable (bytes) + +unallocated (12) + +address (20) - + -7:13->2 - - - - - -3 - -address[]: rewardTokenAddresses <<Array>> -0xa2999d817b6757290b50e8ecf3fa939673403dd35c97de392fdb343b4015ce9e - -offset - -0 - -type: variable (bytes) - -unallocated (12) - -address (20) - - - -7:18->3 - - - - - -4 - -int256[98]: _reserved <<Array>> - -slot - -59 - -60 - -61-154 - -155 - -156 - -type: variable (bytes) - -int256 (32) - -int256 (32) - ----- (3008) - -int256 (32) - -int256 (32) - - - -7:24->4 - - - - - -5 - -int256[48]: __reserved <<Array>> - -slot - -159 - -160 - -161-204 - -205 - -206 - -type: variable (bytes) - -int256 (32) - -int256 (32) - ----- (1408) - -int256 (32) - -int256 (32) - - - -7:32->5 - - - - - -6 - -int256[50]: __reserved_baseAuraStrategy <<Array>> - -slot - -207 - -208 - -209-254 - -255 - -256 - -type: variable (bytes) - -int256 (32) - -int256 (32) - ----- (1472) - -int256 (32) - -int256 (32) - - - -7:38->6 - - +3:13->2 + + diff --git a/contracts/docs/generate.sh b/contracts/docs/generate.sh index 8a54e1fa11..377c5f7aa8 100644 --- a/contracts/docs/generate.sh +++ b/contracts/docs/generate.sh @@ -79,7 +79,7 @@ sol2uml storage .. -c MorphoCompoundStrategy -o MorphoCompStrategyStorage.svg -- # contracts/strategies/balancer sol2uml .. -v -hv -hf -he -hs -hl -b BalancerMetaPoolStrategy -o BalancerMetaPoolStrategyHierarchy.svg sol2uml .. -s -d 0 -b BalancerMetaPoolStrategy -o BalancerMetaPoolStrategySquashed.svg -sol2uml storage .. -c BalancerMetaPoolStrategy -o BalancerMetaPoolStrategyStorage.svg +sol2uml storage .. -c BalancerMetaPoolStrategy -o BalancerMetaPoolStrategyStorage.svg --hideExpand ______gap,_reserved,__reserved,__reserved_baseAuraStrategy # contracts/swapper sol2uml .. -v -hv -hf -he -hs -hl -b Swapper1InchV5 -o Swapper1InchV5Hierarchy.svg From 6b5a2b486f75d34e08c02c2235fec4c5ad1533a3 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Mon, 11 Sep 2023 23:37:44 +0200 Subject: [PATCH 64/67] bug fix --- contracts/test/_fixture.js | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 300e829f0f..b910669ebc 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -3,7 +3,6 @@ const { ethers } = hre; const { BigNumber } = ethers; const { expect } = require("chai"); const { formatUnits } = require("ethers/lib/utils"); -const { ethers } = hre; const addresses = require("../utils/addresses"); const { setFraxOraclePrice } = require("../utils/frax"); From 09684fd94db04ba9e32fb81eacbd4a813cadc9bf Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Tue, 12 Sep 2023 00:16:59 +0200 Subject: [PATCH 65/67] bug fix --- contracts/test/_fixture.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index b910669ebc..52be534be1 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -225,8 +225,8 @@ const defaultFixture = deployments.createFixture(async () => { mockSwapper, swapper1Inch, mock1InchSwapRouter, - ConvexEthMetaStrategyProxy, - ConvexEthMetaStrategy, + convexEthMetaStrategyProxy, + convexEthMetaStrategy, fluxStrategy, vaultValueChecker, oethVaultValueChecker; @@ -337,7 +337,7 @@ const defaultFixture = deployments.createFixture(async () => { oethHarvesterProxy.address ); - const convexEthMetaStrategyProxy = await ethers.getContract( + convexEthMetaStrategyProxy = await ethers.getContract( "ConvexEthMetaStrategyProxy" ); convexEthMetaStrategy = await ethers.getContractAt( From c1e1cf2fa03c4086c6dc89f38f3a55fcaf463839 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Wed, 13 Sep 2023 23:25:27 +0200 Subject: [PATCH 66/67] correct script to balance the pool --- brownie/abi/balancer_metastablepool.json | 1437 +++++++++++++++++ brownie/abi/balancer_vault.json | 1 + brownie/abi/reth.json | 225 +++ brownie/abi/vault_core.json | 13 + .../amm_strat_report-checkpoint.ipynb | 1023 ++++++++++++ brownie/balancer_test/amm_strat_report.ipynb | 1374 ++++++++++++++++ brownie/balancer_test/balance_stats.csv | 31 + brownie/balancer_test/deposit_stats.csv | 306 ++++ brownie/balancer_test/strategy_harness.py | 299 ++++ brownie/balancer_test/withdraw_stats.csv | 31 + brownie/balancer_test/withdrawall_stats.csv | 7 + brownie/scripts/strategy_harness.py | 307 ++++ brownie/world.py | 3 +- .../balancer/BalancerMetaPoolStrategy.sol | 16 +- .../balancer/BaseBalancerStrategy.sol | 6 +- contracts/contracts/vault/VaultCore.sol | 4 + contracts/deploy/066_oeth_vault_swaps.js | 6 +- .../deployments/mainnet/.migrations.json | 1 - 18 files changed, 5078 insertions(+), 12 deletions(-) create mode 100644 brownie/abi/balancer_metastablepool.json create mode 100644 brownie/abi/balancer_vault.json create mode 100644 brownie/abi/reth.json create mode 100644 brownie/balancer_test/.ipynb_checkpoints/amm_strat_report-checkpoint.ipynb create mode 100644 brownie/balancer_test/amm_strat_report.ipynb create mode 100644 brownie/balancer_test/balance_stats.csv create mode 100644 brownie/balancer_test/deposit_stats.csv create mode 100644 brownie/balancer_test/strategy_harness.py create mode 100644 brownie/balancer_test/withdraw_stats.csv create mode 100644 brownie/balancer_test/withdrawall_stats.csv create mode 100644 brownie/scripts/strategy_harness.py diff --git a/brownie/abi/balancer_metastablepool.json b/brownie/abi/balancer_metastablepool.json new file mode 100644 index 0000000000..1ae16a106b --- /dev/null +++ b/brownie/abi/balancer_metastablepool.json @@ -0,0 +1,1437 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "contract IRateProvider[]", + "name": "rateProviders", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "priceRateCacheDuration", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "amplificationParameter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "oracleEnabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "internalType": "struct MetaStablePool.NewPoolParams", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "startValue", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endValue", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + } + ], + "name": "AmpUpdateStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "currentValue", + "type": "uint256" + } + ], + "name": "AmpUpdateStopped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "OracleEnabledChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "PausedStateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rate", + "type": "uint256" + } + ], + "name": "PriceRateCacheUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IRateProvider", + "name": "provider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "cacheDuration", + "type": "uint256" + } + ], + "name": "PriceRateProviderSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + } + ], + "name": "SwapFeePercentageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAmplificationParameter", + "outputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isUpdating", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "precision", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLargestSafeQueryWindow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getLastInvariant", + "outputs": [ + { + "internalType": "uint256", + "name": "lastInvariant", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastInvariantAmp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IPriceOracle.Variable", + "name": "variable", + "type": "uint8" + } + ], + "name": "getLatest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOracleMiscData", + "outputs": [ + { + "internalType": "int256", + "name": "logInvariant", + "type": "int256" + }, + { + "internalType": "int256", + "name": "logTotalSupply", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "oracleSampleCreationTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "oracleIndex", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "oracleEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IPriceOracle.Variable", + "name": "variable", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "ago", + "type": "uint256" + } + ], + "internalType": "struct IPriceOracle.OracleAccumulatorQuery[]", + "name": "queries", + "type": "tuple[]" + } + ], + "name": "getPastAccumulators", + "outputs": [ + { + "internalType": "int256[]", + "name": "results", + "type": "int256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPausedState", + "outputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "pauseWindowEndTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodEndTime", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "name": "getPriceRateCache", + "outputs": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expires", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRateProviders", + "outputs": [ + { + "internalType": "contract IRateProvider[]", + "name": "providers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getSample", + "outputs": [ + { + "internalType": "int256", + "name": "logPairPrice", + "type": "int256" + }, + { + "internalType": "int256", + "name": "accLogPairPrice", + "type": "int256" + }, + { + "internalType": "int256", + "name": "logBptPrice", + "type": "int256" + }, + { + "internalType": "int256", + "name": "accLogBptPrice", + "type": "int256" + }, + { + "internalType": "int256", + "name": "logInvariant", + "type": "int256" + }, + { + "internalType": "int256", + "name": "accLogInvariant", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getScalingFactors", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSwapFeePercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IPriceOracle.Variable", + "name": "variable", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "secs", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ago", + "type": "uint256" + } + ], + "internalType": "struct IPriceOracle.OracleAverageQuery[]", + "name": "queries", + "type": "tuple[]" + } + ], + "name": "getTimeWeightedAverage", + "outputs": [ + { + "internalType": "uint256[]", + "name": "results", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalSamples", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "onExitPool", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amountsOut", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "dueProtocolFeeAmounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "onJoinPool", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amountsIn", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "dueProtocolFeeAmounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "contract IERC20", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IPoolSwapStructs.SwapRequest", + "name": "request", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "indexIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "indexOut", + "type": "uint256" + } + ], + "name": "onSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "contract IERC20", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IPoolSwapStructs.SwapRequest", + "name": "request", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "balanceTokenIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceTokenOut", + "type": "uint256" + } + ], + "name": "onSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "queryExit", + "outputs": [ + { + "internalType": "uint256", + "name": "bptIn", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "amountsOut", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "queryJoin", + "outputs": [ + { + "internalType": "uint256", + "name": "bptOut", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "amountsIn", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "bytes", + "name": "poolConfig", + "type": "bytes" + } + ], + "name": "setAssetManagerPoolConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "setPriceRateCacheDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + } + ], + "name": "setSwapFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "rawEndValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + } + ], + "name": "startAmplificationParameterUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stopAmplificationParameterUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "name": "updatePriceRateCache", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/brownie/abi/balancer_vault.json b/brownie/abi/balancer_vault.json new file mode 100644 index 0000000000..683e4bf7b7 --- /dev/null +++ b/brownie/abi/balancer_vault.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"contract IAuthorizer","name":"authorizer","type":"address"},{"internalType":"contract IWETH","name":"weth","type":"address"},{"internalType":"uint256","name":"pauseWindowDuration","type":"uint256"},{"internalType":"uint256","name":"bufferPeriodDuration","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IAuthorizer","name":"newAuthorizer","type":"address"}],"name":"AuthorizerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExternalBalanceTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IFlashLoanRecipient","name":"recipient","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"FlashLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"int256","name":"delta","type":"int256"}],"name":"InternalBalanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"PausedStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"liquidityProvider","type":"address"},{"indexed":false,"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"int256[]","name":"deltas","type":"int256[]"},{"indexed":false,"internalType":"uint256[]","name":"protocolFeeAmounts","type":"uint256[]"}],"name":"PoolBalanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"assetManager","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"int256","name":"cashDelta","type":"int256"},{"indexed":false,"internalType":"int256","name":"managedDelta","type":"int256"}],"name":"PoolBalanceManaged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"poolAddress","type":"address"},{"indexed":false,"internalType":"enum IVault.PoolSpecialization","name":"specialization","type":"uint8"}],"name":"PoolRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"RelayerApprovalChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":true,"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"name":"TokensDeregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"assetManagers","type":"address[]"}],"name":"TokensRegistered","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IVault.SwapKind","name":"kind","type":"uint8"},{"components":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"uint256","name":"assetInIndex","type":"uint256"},{"internalType":"uint256","name":"assetOutIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct IVault.BatchSwapStep[]","name":"swaps","type":"tuple[]"},{"internalType":"contract IAsset[]","name":"assets","type":"address[]"},{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.FundManagement","name":"funds","type":"tuple"},{"internalType":"int256[]","name":"limits","type":"int256[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"batchSwap","outputs":[{"internalType":"int256[]","name":"assetDeltas","type":"int256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"name":"deregisterTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address payable","name":"recipient","type":"address"},{"components":[{"internalType":"contract IAsset[]","name":"assets","type":"address[]"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.ExitPoolRequest","name":"request","type":"tuple"}],"name":"exitPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IFlashLoanRecipient","name":"recipient","type":"address"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"flashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"getActionId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAuthorizer","outputs":[{"internalType":"contract IAuthorizer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"name":"getInternalBalance","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNextNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPausedState","outputs":[{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"uint256","name":"pauseWindowEndTime","type":"uint256"},{"internalType":"uint256","name":"bufferPeriodEndTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"}],"name":"getPool","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"enum IVault.PoolSpecialization","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"getPoolTokenInfo","outputs":[{"internalType":"uint256","name":"cash","type":"uint256"},{"internalType":"uint256","name":"managed","type":"uint256"},{"internalType":"uint256","name":"lastChangeBlock","type":"uint256"},{"internalType":"address","name":"assetManager","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"}],"name":"getPoolTokens","outputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"balances","type":"uint256[]"},{"internalType":"uint256","name":"lastChangeBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProtocolFeesCollector","outputs":[{"internalType":"contract ProtocolFeesCollector","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"relayer","type":"address"}],"name":"hasApprovedRelayer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"contract IAsset[]","name":"assets","type":"address[]"},{"internalType":"uint256[]","name":"maxAmountsIn","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"}],"internalType":"struct IVault.JoinPoolRequest","name":"request","type":"tuple"}],"name":"joinPool","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"enum IVault.PoolBalanceOpKind","name":"kind","type":"uint8"},{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IVault.PoolBalanceOp[]","name":"ops","type":"tuple[]"}],"name":"managePoolBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum IVault.UserBalanceOpKind","name":"kind","type":"uint8"},{"internalType":"contract IAsset","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct IVault.UserBalanceOp[]","name":"ops","type":"tuple[]"}],"name":"manageUserBalance","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum IVault.SwapKind","name":"kind","type":"uint8"},{"components":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"uint256","name":"assetInIndex","type":"uint256"},{"internalType":"uint256","name":"assetOutIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct IVault.BatchSwapStep[]","name":"swaps","type":"tuple[]"},{"internalType":"contract IAsset[]","name":"assets","type":"address[]"},{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.FundManagement","name":"funds","type":"tuple"}],"name":"queryBatchSwap","outputs":[{"internalType":"int256[]","name":"","type":"int256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IVault.PoolSpecialization","name":"specialization","type":"uint8"}],"name":"registerPool","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"address[]","name":"assetManagers","type":"address[]"}],"name":"registerTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAuthorizer","name":"newAuthorizer","type":"address"}],"name":"setAuthorizer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"relayer","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setRelayerApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"enum IVault.SwapKind","name":"kind","type":"uint8"},{"internalType":"contract IAsset","name":"assetIn","type":"address"},{"internalType":"contract IAsset","name":"assetOut","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct IVault.SingleSwap","name":"singleSwap","type":"tuple"},{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.FundManagement","name":"funds","type":"tuple"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountCalculated","type":"uint256"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/brownie/abi/reth.json b/brownie/abi/reth.json new file mode 100644 index 0000000000..0f83e9a06a --- /dev/null +++ b/brownie/abi/reth.json @@ -0,0 +1,225 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_rethAmount", + "type": "uint256" + } + ], + "name": "getEthValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_ethAmount", + "type": "uint256" + } + ], + "name": "getRethValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] \ No newline at end of file diff --git a/brownie/abi/vault_core.json b/brownie/abi/vault_core.json index 2588db7623..b4e5f27929 100644 --- a/brownie/abi/vault_core.json +++ b/brownie/abi/vault_core.json @@ -972,6 +972,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalValueInVault", + "outputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/brownie/balancer_test/.ipynb_checkpoints/amm_strat_report-checkpoint.ipynb b/brownie/balancer_test/.ipynb_checkpoints/amm_strat_report-checkpoint.ipynb new file mode 100644 index 0000000000..b8f1cbbea8 --- /dev/null +++ b/brownie/balancer_test/.ipynb_checkpoints/amm_strat_report-checkpoint.ipynb @@ -0,0 +1,1023 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "0693ee63-df90-468e-964b-e19a6ee3df8f", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'retina'\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5b49a2fe-554f-427a-887b-b3880bf941f2", + "metadata": {}, + "outputs": [], + "source": [ + "def load_data(filename):\n", + " base = pd.read_csv(filename)\n", + " for x in base:\n", + " if \" \" in x or \"action\" in x:\n", + " continue\n", + " else:\n", + " base[x] = base[x].apply(int)\n", + " base['pre_mix'] = base['pre_pool_0'] / (base['pre_pool_0'] + base['pre_pool_1'])\n", + " base['before_mix'] = base['before_pool_0'] / (base['before_pool_0'] + base['before_pool_1'])\n", + " base['after_mix'] = base['after_pool_0'] / (base['after_pool_0'] + base['after_pool_1'])\n", + " base['before_profit'] = base['before_vault'] - base['pre_vault']\n", + " base['after_profit'] = base['after_vault'] - base['before_vault']\n", + " return base\n", + "\n", + "base = load_data(\"deposit_stats.csv\")\n", + "balance_base = load_data(\"balance_stats.csv\")\n", + "withdraw_base = load_data(\"withdraw_stats.csv\")\n", + "withdrawall_base = load_data(\"withdrawall_stats.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4273c012-881a-4a28-8f1a-6242f8c65195", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 428, + "width": 546 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = base\n", + "plt.axhline(0, c=\"grey\", linewidth=0.5)\n", + "plt.axhline(0, c=\"black\", linewidth=0.4)\n", + "for before_mix, rows in df.groupby(df['before_mix']):\n", + " plt.plot(rows['action_mix'], rows['after_profit'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "34c14a7e-adf1-445c-97fc-8bec0a003dcc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABJcAAAOMCAYAAADwv1I+AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/OQEPoAAAACXBIWXMAAB7CAAAewgFu0HU+AAEAAElEQVR4nOzdd3iUVdrH8e9Mem90SAIkdFCUJiACiogUFRVBQYpYXte2u1hWd1dRd9dV11111V0VpCgKioAUC6KgAqGKAlITIBQhkIT0Opl5/8hmwjPpIcmT8vtcl9c1cz/nOXNnomZy55z7WBwOhwMREREREREREZFqsJqdgIiIiIiIiIiINFwqLomIiIiIiIiISLWpuCQiIiIiIiIiItWm4pKIiIiIiIiIiFSbiksiIiIiIiIiIlJtKi6JiIiIiIiIiEi1qbgkIiIiIiIiIiLVpuKSiIiIiIiIiIhUm4pLIiIiIiIiIiJSbSouiYiIiIiIiIhItam4JCIiIiIiIiIi1abikoiIiIiIiIiIVJuKSyIiIiIiIiIiUm0qLomIiIiIiIiISLWpuCQiIiIiIiIiItWm4pKIiIiIiIiIiFSbiksiIiIiIiIiIlJtKi6JiIiIiIiIiEi1qbgkIiIiIiIiIiLVpuKSiIiIiFTK7NmzsVgsWCwWZs+ebXY6jVZSUhLPPvssAwYMICQkBDc3N+f7Pn/+fACOHTvmjLVv397UfEVERNzNTkBEREQEYNiwYXz33XelXvPy8iIoKIjAwEBatmzJZZddRp8+fbj66quJiIio40xFas+RI0e46qqrOHXqlNmpiIiIVJqKSyIiIlLv5ebmcvbsWc6ePUtsbCybNm0CwGq1MmrUKB5++GGuu+46k7MUgA0bNjB8+HAAhg4dyoYNG8xNqIG57777nIUlHx8fRowYQdu2bXFzcwOgW7duVZqvffv2xMfHA3D06FGtchIRkVqh4pKIiIjUO/369aN///7O53a7ndTUVFJSUvjll1+cvyzb7XY+//xzPv/8c6ZPn87rr79OQECAWWmLXJTTp0+zbt06oHC13s8//0ynTp1MzkpERKRiKi6JiIhIvTN69Ohye/qcOXOG999/n9dff52TJ08CMH/+fH755Re+++47fHx86ijTpmX27NnqtVSLdu3a5Xw8ZMiQcgtL7du3x+Fw1EVaIiIiFVJDbxEREWlwWrVqxWOPPcb+/fuZMGGCM759+3amT59uXmIiF+H8+fPOx61btzYxExERkapRcUlEREQaLH9/f5YsWcKYMWOcsY8//pjvv//exKxEqic/P9/52GrVx3QREWk49FNLREREGjSLxcLChQsNvZb++te/Vure/fv389RTT9G/f39atmyJp6cnzZs3Z8CAATz99NP8+uuvFc4xbNgw55HwRc2rT5w4wZ/+9CcuvfRSQkND8fPzo2vXrvzud78jNja2Sl9fRkYGr7/+Otdddx3t2rXD29ubkJAQevbsyYMPPsjWrVsrPdeJEyd49tlnueqqq2jZsiVeXl54enoSFhbGpZdeyh133MF//vMfzpw5U+r9s2fPdn6trtvjiq4VNfMG+O6775zjL/znYppK18b7XdrXlZ2dzdy5cxk5ciQRERF4enpisVj46aefStx/Md+jDRs2OF97xowZzviCBQtKvG8Xrso7duxYme/nhdeK+pMBdOjQodTvh5qui4jIxVLPJREREWnwQkNDmT59Ov/+978B+Prrr0lOTiY0NLTU8bm5uTzyyCPMmTOHgoICw7XExEQSExPZtm0b//jHP3jppZd48MEHK53LypUrmTp1KqmpqYb4wYMHOXjwIG+//Tavvvoq9957b4VzrV69mnvuuadEsSc3N9fZ3PzNN9/kjjvu4N1338XX17fMud555x1++9vfkp2dXeJacnIyycnJ7N69m48++ohFixaxcePGSn7F5qrJ97tI0XbLX375pcKxNfk9EhERaahUXBIREZFGYcKECc7iksPhYOPGjdxwww0lxmVmZnLdddexadMmZywqKoo+ffoQEhJCcnIymzZt4tdffyU7O5uHHnqItLQ0nnrqqQpz2LFjB3/84x/Jy8sjLCyMYcOGERISwrFjx/juu+/Iz88nOzub++67Dzc3N2bOnFnmXEuWLGHy5MnO4pebmxtXXnkl0dHRZGRk8MMPPzhXVn344YccPXqUb7/9Fm9v7xJzrVixgvvuu8/5PDAwkIEDB9KuXTvc3d1JTU3l0KFD7N27l7y8vAq/ztL079+fBx54gFOnTrFixQoA2rRpw/jx40uMDQsLq9ZruKrJ97tIUlISo0aN4vjx43h7e3PllVcSGRlJRkYGW7ZsMYytie9R27ZteeCBBwA4cOAA33zzDQBdu3blmmuuMbzeFVdcUan3JTAw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3OAc89lnn5XaI7C+qYn3uzpq+3skIiLS0Ki4JI3ezz//TNeuXXnooYf49ttvSUhIID8/n3PnzvHNN99w9913M2jQIBISEmothy5dujgfHzlypMxxcXFxpd4jIiLlS0pKYsGCBc7no0aNKnGKWO/evZ39hM6ePUtsbGyN57Fly5YKxxQUFBiahF9++eWG65dddpnz8bZt2yq1RW3z5s2G+6uy4qioELdixQquvfZaZ3zlypWVnuNCdbnaqSbe7+qo6+/Rxajvq89ERKRxUHFJGrXY2FiGDh1KfHw8gYGBPPnkkyxfvpwdO3bw1Vdf8cADD+Du7s727du58cYbyc/Pr5U8evXqxaBBgwCYP3++oalskfT0dF599VWgcHXTyJEjayUXEZHGxuFwMG3aNEMfnD/96U8lxvn4+HD11Vc7n7/11ls1nsvKlStJS0srd8yXX37J2bNnAfD29i5x4tmgQYOcRbBz586xZs2acuez2+3MmzfP+fzCr7EqLBYL48aNcz6v7h9dvL29nY9r6+dqkZp4v6vDrO9RddTl90NERJouFZekUZs2bRqpqalcdtllxMXF8be//Y2bbrqJPn36MHLkSN544w1WrVqF1Wpl69atzJ8/v9ZymTdvHh06dCA5OZnLL7+cf/7zn2zYsIGNGzfy3//+l0svvZSjR4/SrFkzFi1ahKenZ63lIiLSWGRkZDBp0iTDL/d33nlnmQWEJ554wvn43//+N+vWrav0a1VmK11aWhpPPfVUmdczMzN5/PHHnc9vvfXWEiusgoODmThxovP5Y489Vm7z5zfeeMN5gqnVauXee+81XE9PT6/0VusLt4+1aNGiUve4CgsLcz4+depUteaorJp4v6ujpr9Htakuvx8iItJ0qbgkjdYPP/zgXIK+YMGCMnssjBo1iltvvRWgVotLnTt3Zvv27Tz//PNkZmY6T4sbMmQI999/PydPnuTRRx9l165dJZrQioiI0ZkzZ/jHP/5B9+7d+fjjj53xQYMG8e6775Z539ChQ5k2bRpQePLbmDFjeOGFFwyrni6Uk5PDihUruPHGGw09icri6enJm2++yR/+8IcSBZ1Tp04xZswY9u3bBxSupHrmmWdKnefpp592No0+dOgQ1113XYlt1Xa7nddee43f//73ztgDDzxgOPIeYOfOnbRv357Zs2c7X9tVQUEBS5Ys4d///rczdv3111f49ZamQ4cOzlPc4uPjDVvSalpNvd/VUZPfo9rUs2dP5+ML+5KJiIjUJJ0WJ41WUa+ILl260KtXr3LHXnXVVXz88cds374dm82Gu3vt/KexatUqFi1aVOovMfn5+Xz88cc0b96cxx57TD0SRKRJ+/zzz50nmEHhL+lpaWmkpKSwb98+jh49WuKee+65h3/961/O7Uplefvttzl9+jRr164lLy+Pp556ir/85S8MGDCAiIgIvLy8SElJIS4ujr1795KbmwtAnz59Ksz7L3/5C3/84x958cUXmTt3LsOGDSMkJIT4+Hg2bNhgKIC8+uqrREdHlzpPVFQUc+bMYfLkyRQUFBATE0OXLl0YMmQIUVFRZGRk8MMPPxhWolxxxRW89NJLpc53+vRpnn32WZ599llatWpF7969adWqFe7u7iQkJLBz507Dlu0hQ4YwadKkCr/e0ri5uXHTTTfx4YcfAjBs2DBGjRpFREQEbm5uAISGhpa74qiyaur9ro6a/h7VlltuuYW3334bKNwKunPnTi6//HJnARDg/vvvNxwqIiIiUmUOkQbi6NGjDsABOKZNm1bh+GHDhjnHV+WfhISECud+5plnnOPXr19fqfx///vfO++56aabHJs2bXJkZGQ4srOzHT/++KNjxowZzus333yzw2azVWpeEZHGYujQoVX+f7abm5tj7NixjnXr1lXptWw2m+PPf/6zw9fXt1Kv4+Hh4XjggQcqzHv9+vWOFStWOAIDA8ucy9vb2/HWW29VKs9Vq1Y5WrZsWWF+t99+uyMzM7PUObZs2eJwd3ev9Ht66623OtLS0kqd68Kff88880yZeR87dszRqlWrMl8jMjKyUl9/aWrj/a7s11WamvgeFZk3b16lP+tc+Lmoovfz9ttvLze3yn6WERERKYtWLkmjVdS8s6qysrJqOBNYs2YN//znPwGYPn26oaknFJ4a895779GuXTuef/55li1bxltvvcVDDz1U47mIiDREnp6eBAYGEhQURKtWrbjsssvo06cPI0aMoF27dlWez83Njeeee46HHnqIhQsXsm7dOvbt20diYiL5+fkEBgYSGRlJr169GD58OKNHjzYcP1+eG2+8kd27d/Pf//6XNWvWcPz4cfLy8ggPD2fUqFE8+OCDdOrUqVJzjR07ltjYWN577z1Wr17NL7/8QmJiIj4+PrRp04bhw4czdepUBgwYUOYcAwYM4OzZs6xbt46NGzeya9cu4uLiSEpKoqCggMDAQKKiorjiiiuYMmUK/fv3r1Ru5YmMjOTnn3/mjTfeYO3atRw6dIj09HRsNttFz+2qJt/v6qiJ71FtW7RoEWPHjuWjjz7ip59+IjExkZycHNPyERGRxsficDgcZichUhnHjh2jQ4cOQGGj7or6I3Xt2pWDBw9y6aWX8sEHH1T6dbp06YKHh0e5Y2bPns2zzz4LwPr16xk2bFi548ePH8+KFSuwWCycOHGCtm3bljouJyeH5s2bk5GRQe/evdm1a1el8xYREXMMGzaM7777DqjczwS5OHq/RURE6h+tXJJGq+h0lIyMDEMzSzPs378fKDx5p6zCEhQeF9yjRw+2bt3KgQMH6io9ERERERERkWrTaXHSaF122WUAHDlypFLHR9emogbhldkOkJ+fb7hHREREREREpD5TcUkaraIjox0OB6+99pqpuRRt50tKSnKuYipNcnIye/fuNdwjIiIiIiIiUp+puCSN1siRI51NSV9++WU+/vjjcsfv2bOHVatW1Uou48aNcz7+7W9/azgauYjdbufhhx92Xhs7dmyt5CIiIiIiIiJSk7TvRuqtjRs3Ehsb63yemJjofBwbG1uioff06dNLzPHhhx/Sv39/kpOTmThxIh988AETJ06kU6dOuLm5cfbsWXbt2sWqVavYsmULs2bNMhSCiri+1k8//eR8/OWXX3Ls2DHn8+joaK688soSub366qvs37+ftWvX0rdvXx566CEuvfRS3Nzc2LdvH//5z3+IiYkBoGXLlvz+97+v4B0SERERERERMZ9Oi5N6a/r06SxYsKDS48v6V/nQoUPccsstzu1m5Xn22Wd5+umnS8QtFkul8yjrJLv4+HhuvPFGfv7553Lv79ChA8uWLaN3796Vfk0RETGPTi+rW3q/RURE6h+tXKoFZ8+eZdu2bWzbto3t27ezfft2kpKSgLILDxfro48+Yt68eezevZuUlBRatmzJkCFDeOCBBxg4cGCl5sjKyuKNN97gk08+IS4ujtzcXMLDwxkzZgwPP/wwkZGRNZ53XejcuTM//fQTH3/8MZ9++inbt2/n3LlzFBQUEBYWRpcuXbjyyisZP348l19+ea3lERkZyfbt21m8eDFLly7lxx9/5Ny5czgcDkJDQ7nkkku46aabmDp1Kn5+frWWh4iI1KwNGzaYnUKTovdbRESk/tHKpVpQ3iqXmi4uZWdnc+utt/L555+Xet1qtfL000/zzDPPlDtPbGwso0eP5vDhw6VeDwwMZNGiReoDJCIiIiIiIiIGauhdyyIiIhg5cmStzX/XXXc5C0vDhw9nxYoVbNu2jblz5xIVFYXdbmf27Nm88847Zc6Rnp7OmDFjnIWle+65h2+++YbNmzfz17/+FX9/f9LS0pg4caKh15CIiIiIiIiIiFYu1YJnnnmGfv360a9fP1q2bMmxY8ecx8rX5Mqlb7/9lmuuuQYoPI1s+fLluLm5Oa8nJibSp08fjh8/TnBwMEeOHCEkJKTEPE8//TTPP/88AC+99BKPPfaY4frmzZsZOnQoNpuNoUOHajm6iIiIiIiIiDhp5VItePbZZxk7diwtW7as1df5xz/+AYC7uztvvfWWobAE0KxZM1588UUAUlJSmDNnTok58vPzef311wHo1q0bs2bNKjFm0KBBzJw5E4DvvvuO7du31+jXISIiIiIiIiINl4pLDVR6ejrffPMNACNGjKBdu3aljrv55psJDAwEYPny5SWur1+/ntTUVKBwVZXVWvq/EtOnT3c+Lm0eEREREREREWmaVFxqoLZv305eXh4AQ4cOLXOcp6cnV1xxhfOe/Px8w/WNGzc6H5c3T9++ffH19QVg06ZN1c5bRERERERERBoXd7MTkOrZt2+f83HXrl3LHdu1a1fWrl2LzWbj8OHDdO/evcrzuLu7Ex0dze7du9m/f3+V8z158mS513Nycjhw4AAtW7akefPmuLvrX00RERERERGRmmaz2Th37hwAvXr1wtvb+6Ln1G/wDdSFxZqytsQVCQ8Pdz4+ceKEobhUNI+fnx/BwcEVzrN7927OnTtHbm4uXl5elc73whxERERERERExHzbtm2jX79+Fz2PtsU1UOnp6c7H/v7+5Y718/NzPs7IyCh1normqGgeEREREREREWmatHKpgcrJyXE+9vT0LHfshSuMsrOzS52nojkqmqciJ06cqPD6oEGDgMLKaevWras0v0i94XDArg9gw98Bu/FaYFu46b/QLNqU1ESk8Xnsk5/54XCi8/mYS1rz57Hdy7lD6qufvjnOT18Xf14KDPPm5sf6mJiRiIg0VqdPn6Z///4ANG/evEbmVHGpgbpwT2RR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c3M1ceJE8/v+/fsXGHPs2DHzuKicDw8PN4/JeZSWF154QadOnVLbtm312GOPFfs8chllSW5urvbt2ydJCgoK0siRIzVo0CDt2rXLZtyBAwc0atQode7cWRcuXLDpI6dR1gQFBenTTz9V5cqVtWHDBkVFRemTTz7R5s2bFRcXp/Hjx6tDhw7KzMzU7bffrv/85z8255PTKC9clavOzGMYhs15ZRHFJaAYLl26ZB77+/sXOT6vuJSamlpqMQHOmjJlirZs2SJJ6tevn93bPEuS83n5LpHzKB3r1q3T9OnT5eXlpQ8//FAWi6XY55LLKEsuXryo3NxcSdLOnTv1zjvvKCQkRHPnzlVycrLS0tK0du1acx+PjRs3Kjo62mYOchpl0QMPPKDt27dr+PDh+vnnnzVkyBC1adNG3bp1U2xsrCpXrqy3335b69atU+3atW3OJadRXrgqVytqzlNcAoohPT3dPPb29i5yvI+PjyTpypUrpRYT4Iy1a9dqzJgxkqTg4GB98MEHdseVJOfz8l0i5+F6mZmZevzxx2UYhp577jm1atWqROeTyyhLrG9pSE9PV+XKlRUfH69BgwapRo0a8vPz0z333KM1a9botttuk3R1E9cff/zR5rw85DTKiszMTH3yyScON9o+ffq05s6dq7i4uAJ95DTKC1flakXNeYpLQDH4+vqax9ZPt3Akb48EPz+/UosJKKndu3erb9++ys7Olq+vrxYtWqTg4GC7Y0uS89Z7gpDzcLXXX39d+/btU7169RQTE1Pi88lllCXW+ShJw4cPt9kMOY+fn59ee+018/vPP//c7hzkNMqCy5cvq2vXrnrjjTeUnJysF154QXv37lVGRoYuXryoVatWqV27dtq2bZv69Omjt956y+Z8chrlhatytaLmPMUloBiqVq1qHhdnOWLeXyaLcwsdcCMkJiaqe/fuOn/+vDw9PbVgwQLdc889DseXJOet/xJPzsOV9u3bpzfeeEOS9O6779osDS8uchlliXU+SlL37t0dju3SpYv5AJGtW7fanYOcRlkQGxurdevWSZJmzJihSZMmqXnz5vL29lZAQIC6deum+Ph4derUSYZhaNSoUfrll1/M88lplBeuytWKmvOOH3kFwOTr66uaNWvq3LlzRW6kdv78efOXgPVGboC7nDhxQl27dtWJEydksVg0c+ZM9e7du9BzrDcXLCrnrTcpJOfhSlOmTFFmZqYaNWqktLQ0LViwoMAY642Q16xZo1OnTkmSevXqpSpVqpDLKFN8fHxUq1YtJSUlSSo8z3x9fRUUFKRTp06Z4yV+P6NsMQxDM2fOlCRFRERoyJAhdsd5eXlpwoQJateunXJzczV79mxNmTJFEjmN8sNVuZp/nsKegJs3j8ViKXLzb3ejuAQUU4sWLbRu3Tr99ttvys7ONv+amF/eU2Ak+494B26ks2fPqlu3bjp06JCkq6s/Bg8eXOR5LVq0MI+tc9oech6lJW8p+KFDhzRgwIAix0+YMME8TkxMVJUqVchllDktW7ZUQkKCJNl9ZLu1vH7r9xzkNMqS06dPKzk5WZLUunXrQsdaP0DEOjfJaZQXrsrV/PP88Y9/LHKe8PBwp1Zw30jcFgcUU7t27SRdXZq4fft2h+PWrl1rHrdt27bU4wIcuXjxonr06KE9e/ZIkiZOnKgRI0YU69yGDRsqNDRUkm1O2/PDDz9IkurWrasGDRo4HzBQCshllDXWtyTnFf7tSUlJ0dmzZyVdzck85DTKEuvCZ3Z2dqFjs7Ky7J5HTqO8cFWu5n2uLGqeU6dO6cCBA5LKx+dKiktAMfXp08c8njVrlt0xubm5+uSTTyRJ1atXV6dOnW5EaEABaWlpuu+++7Rjxw5J0ksvvaTRo0cX+3yLxWLeOrdv3z5t3rzZ7rjNmzebf1Hp3bt3iR4RDxRl9uzZMgyj0C/rTb7j4+PN9rw3cuQyypoHH3zQPF66dKnDcUuXLjWfutW+fXuznZxGWRIYGKiAgABJ0qZNmwotMFl/iG7YsKF5TE6jvHBVrkZERJirmRYuXKi0tDS788yePds87tu37/WGX/oMAMXWvn17Q5Lh5eVlbNy4sUD/v//9b0OSIcmIiYm58QEChmFkZGQY3bt3N3Nx5MiRTs2zf/9+w9PT05BkREZGGmlpaTb9aWlpRmRkpPnfxIEDB1wQPVAyMTExZq7Hx8fbHUMuo6zp2bOnIcnw8PAw4uLiCvSfPHnSCAsLMyQZ3t7exrFjx2z6yWmUJQMGDDB/D8fGxtodk5ycbLRo0cIct3LlSpt+chrukJiYaObkkCFDinWOq3J1xowZ5rVHjBhRoP+3334zAgICDElGkyZNjKysrBK/vhuN4hJQAjt27DD8/PwMSYa/v7/x+uuvG5s2bTLWrFljPP744+YviIiICCMlJcXd4eIm1a9fPzMXO3fubPz666/Gzp07HX7t37/f4Vxjxowx52rdurWxYMECY+vWrcaCBQuM1q1bm31jx469ga8QuKY4xSXDIJdRtuzfv9+oXr26Icnw9fU1xowZY/zwww/G1q1bjffff98sLEkyJk2aZHcOchplxd69e43KlSubOderVy9j8eLFxo4dO4yNGzcab731llGvXj2zv0uXLnbnIadR2tatW2fMmjXL/HrzzTfNvGrbtq1N36xZsxzO44pczc7ONtq2bWuOffDBB43vvvvO+PHHH413333XCA4ONv8IsWLFilL4abgexSWghJYtW2ZWke19RUREGAcPHnR3mLiJOcpNR1/169d3OFdOTo4RHR1d6PmPPfaYkZOTc+NeIGCluMUlchllzbp164zatWs7zEeLxWK8/PLLDs8np1GWfP/990ZQUFCR7zk6d+5sJCcn252DnEZpGzJkSIneIzviqlxNSkoyoqKiHM7h4+NjTJs2zdU/hlJjMYz/fzM3gGI7cuSI/vvf/2r58uU6duyYvL291aRJE/3lL3/RM888o8qVK7s7RNzESroHQf369XX48OFCx6xYsUIff/yxtm7dqrNnzyooKEhRUVF64okn1LNnz+uIFrg+sbGxGj9+vKSrey517Nix0PHkMsqSc+fO6d1339WXX36pxMREZWZmKiQkRB07dtSzzz5b5NO3JHIaZce5c+c0Y8YMffvtt9q9e7cuXLggLy8v1alTR1FRURo4cKAeeOCBIt+nkNMoLUOHDtWcOXOKPb6oUokrcjU7O1vTpk3TZ599pr179+ry5csKDQ1Vly5dNHLkSLVs2bLY8bobxSUAAAAAAAA4jafFAQAAAAAAwGkUlwAAAAAAAOA0iksAAAAAAABwGsUlAAAAAAAAOI3iEgAAAAAAAJxGcQkAAAAAAABOo7gEAAAAAAAAp1FcAgAAAAAAgNMoLgEAAAAAAMBpFJcAAAAAAADgNIpLAAAAAAAAcBrFJQAAAAAAADiN4hIAAAAAAACcRnEJAAAAAAAATqO4BAAAAAAAAKdRXAIAAAAAAIDTKC4BAACgVFksFlksFsXGxro7lOsWGxtrvh4AAHAVxSUAAHDTS0hIMAsG1l9eXl4KDAxUw4YNdc899+i5557TkiVLlJmZ6e6Q4cDs2bNt/g0bN25c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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 454, + "width": 587 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = base\n", + "plt.title(\"Deposit profit\")\n", + "plt.axhline(0, c=\"grey\", linewidth=0.5)\n", + "plt.axhline(0, c=\"black\", linewidth=0.4)\n", + "for before_mix, rows in df.groupby(df['before_mix']):\n", + " plt.plot(rows['action_mix']*100, rows['after_profit'], label=\"{:.1f}%\".format(100*float(before_mix)))\n", + "plt.ylim([-1e18,1e18])\n", + "plt.xlabel(\"Deposit Mix\")\n", + "plt.ylabel(\"Deposit Profit\")\n", + "plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "c6e801c3-e642-4a72-b0c7-6e97277ff5dd", + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "unterminated string literal (detected at line 2) (1012423900.py, line 2)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m Cell \u001b[0;32mIn[5], line 2\u001b[0;36m\u001b[0m\n\u001b[0;31m df = df.sort_values(before_mix')\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m unterminated string literal (detected at line 2)\n" + ] + } + ], + "source": [ + "df = base\n", + "df = df.sort_values('before_mix')\n", + "plt.plot(df['before_mix'],df['before_profit'])" + ] + }, + { + "cell_type": "markdown", + "id": "b3774c32-ec43-4ffa-8f6b-f2c722641bd9", + "metadata": {}, + "source": [ + "# Balance check" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "6ad5c3a7-74cc-49bd-8373-4b512a2f8e22", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "787eb355-7d62-4dc8-9f22-7776d96af272", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABEcAAANYCAYAAAAmAYNOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAB7CAAAewgFu0HU+AABfjklEQVR4nO3debxWVaE//s9hRlAQFIfAIRHB8hYJmKEpppQamtXVBlMsDdP6mnHT4hZaNzM1v+btdkuv5JQ53Cwn1CxCRRxwoLTEAXOAIhUVkXnavz/88XwhzuGcA+c5036/X6/zem3Y61lrPXud9Qyfs9feNUVRFAEAAAAoqQ4t3QEAAACAliQcAQAAAEpNOAIAAACUmnAEAAAAKDXhCAAAAFBqwhEAAACg1IQjAAAAQKkJRwAAAIBSE44AAAAApSYcAQAAAEpNOAIAAACUmnAEAAAAKDXhCAAAAFBqwhEAAACg1IQjAAAAQKkJRwAAAIBSE44AAAAApSYcAQAAAEpNOAIAAACUmnAEAAAAKDXhSBW98sorue222zJx4sQceuih2WabbVJTU5OampqMHTu22fqxZs2aPPnkk7niiityyimnZPjw4enatWulL3fffXe9dZx99tmV8g39Ofvss6v+3AAAAGBzdWrpDrRn2223XUt3IUly9dVXN2sYs9Yee+zR7G0CAABAYwlHmslOO+2UwYMH56677mr2touiqGx37tw5e+21V1auXJknnniiwXWccsop+eQnP7nRMqtXr84HP/jBLFy4MFtttVU+9rGPbWqXAQAAoNkIR6po4sSJGT58eIYPH57tttsuL7zwQnbddddm78eee+6Z//zP/8zw4cPz3ve+N926dcvZZ5/dqHCkX79+6dev30bL3HHHHVm4cGGS5F//9V/TvXv3zeo3AAAANAfhSBV95zvfaekuJElGjBiRESNGVL2dq666qrJ93HHHVb09AAAAaAouyNpGLFu2LP/1X/+VD33oQ9l+++3TpUuX9OvXLwcffHAmTZqUVatWtWj/Fi5cmJtvvjlJsuuuu2b//fdv0f4AAABAQzlzpA3405/+lCOPPDIvvvjiev//6quvZsqUKZkyZUouueSS3HrrrS12Edj//d//zdKlS5Mkn/vc51JTU9Mi/QAAAIDGEo60crNnz84BBxyQN998M1tttVVOPfXUjBgxIgMGDMhr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jRqVCy+8MAsWLGiy9gAAAID2o1M1K99uu+2qWX2S5I477shRRx2V5cuXb7Bv/vz5ufvuu3P33Xfnhz/8YX75y19m1KhRVe8TAAAA0HY027KanXbaKaNHj27yel977bUsX748HTp0yIc//OFcdNFF+cMf/pDHHnsst9xyS4455pgkyT/+8Y989KMfzR//+Mcm7wMAAADQdlX1zJGJEydm+PDhGT58eLbbbru88MIL2XXXXZu0jc6dO2fcuHGZMGFCdtppp/X2DR06NGPGjMnIkSPzf/7P/8mSJUvyta99LX/4wx+atA8AAABA21VTFEXRXI2tG44cf/zxueKKK5qr6QwfPjyPPPJIOnTokJdffjnbbLNNk9Y/d+7cDBgwIEkyZ86c9O/fv0nrBwAAAKrz/bs0d6s58MADkyRr1qzJ888/37KdAQAAAFqN0oQj616wtWPHji3YEwAAAKA1qeo1R1qTe+65J8nb1ygZOHBgox8/d+7cje6fN2/eJvULAAAAaFmlCEcmT56cxx9/PEny4Q9/OFtttVWj61i7ngkAAABoX9r9sprXX389p556apK3l9N897vfbeEeAQAAAK1Juz5zZPXq1fnsZz+bF198MUnyrW99K0OHDt2kuubMmbPR/fPmzcuIESM2qW4AAACg5bTrcOSUU07JnXfemST56Ec/mm9/+9ubXJdb8wIAAED71G6X1Xzzm9/MpZdemiTZf//9c8MNN7hLDQAAALCBdhmOnHfeefnBD36QJHnf+96X2267Ld27d2/hXgEAAACtUbsLR/77v/873/jGN5IkQ4YMyW9/+9tNujsNAAAAUA7tKhy5+uqr8+UvfzlJ8s53vjO///3vs80227RwrwAAAIDWrN2EI7/+9a9zwgknpCiK9O/fP1OmTMmOO+7Y0t0CAAAAWrlWH45cccUVqampSU1NTc4+++xay9x111359Kc/ndWrV6dfv375/e9/n1122aVZ+wkAAAC0TVW9le99992X2bNnV/49f/78yvbs2bNzxRVXrFd+7NixjW7jwQcfzFFHHZUVK1akc+fOueiii7Jy5cr8+c9/rvMx/fv3T+/evRvdFgAAAND+VDUcueyyy3LllVfWum/69OmZPn36ev+3KeHInXfemSVLliRJVq5cmc9+9rP1Pubyyy/fpLYAAACA9qfVL6sBAAAAqKaaoiiKlu5EezB37twMGDAgSTJnzpz079+/hXsEAAAA7U81vn87cwQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAotaqGI6+88kpuu+22TJw4MYceemi22Wab1NTUpKamJmPHjq1Km9dee21Gjx6d7bffPt26dcvOO++cY489Ng888EBV2gMAAADatk7VrHy77barZvXrWbp0aT75yU/m9ttvX+//X3rppVxzzTW59tprM3HixJx11lnN1icAAACg9Wu2ZTU77bRTRo8eXbX6P//5z1eCkVGjRuWmm27KjBkzMmnSpOy2225Zs2ZNzj777Fx66aVV6wMAAADQ9lT1zJGJEydm+PDhGT58eLbbbru88MIL2XXXXZu8nT/84Q+57rrrkiRjxozJb37zm3Ts2DFJMnz48BxxxBHZe++989JLL+XMM8/Mv/7rv2brrbdu8n4AAAAAbU9Vzxz5zne+k49+9KNVX17zwx/+MEnSqVOn/Pd//3clGFlrm222yXnnnZckWbBgQS677LKq9gcAAABoO9r83WreeuutTJkyJUly8MEHp3///rWW+/jHP56tttoqSfKb3/ym2foHAAAAtG5tPhx5+OGHs2LFiiTJAQccUGe5Ll265P3vf3/lMStXrmyW/gEAAACtW1WvOdIcnnzyycr24MGDN1p28ODBueuuu7Jq1ao8++yz2XPPPRvczty5cze6f968eQ2uCwAAAGg92nw4sm5oUdeSmrUGDBhQ2Z4zZ06jwpF1HwsAAAC0H21+Wc1bb71V2e7Zs+dGy/bo0aOyvWjRoqr1CQAAAGg72vyZI8uWLatsd+nSZaNlu3btWtleunRpo9qZM2fORvfPmzcvI0aMaFSdAAAAQMtr8+FIt27dKttrL8xal+XLl1e2u3fv3qh26luyAwAAALRNbX5ZzZZbblnZrm+pzOLFiyvb9S3BAQAAAMqhzYcj657RUd8dZdZdGuMCqwAAAEDSDsKRde8489RTT2207Nr9nTp1yu67717VfgEAAABtQ5sPR4YPH165EOs999xTZ7kVK1bkwQcfrDymc+fOzdI/AAAAoHVr8+HIlltumQ996ENJkt///vd1Lq359a9/nYULFyZJjjrqqGbrHwAAANC6tfpw5IorrkhNTU1qampy9tln11rm3/7t35Ikq1atyqmnnprVq1evt3/+/Pk588wzkyS9e/fOiSeeWNU+AwAAAG1HVW/le99992X27NmVf8+fP7+yPXv27FxxxRXrlR87duwmtXPQQQflU5/6VK677rrccsstOeSQQ/LVr341O+64Y5544omcc845eemll5Ik5513XrbeeutNagcAAABof6oajlx22WW58sora903ffr0TJ8+fb3/29RwJEl+/vOfZ+HChbn99tszderUTJ06db39HTp0yLe//e188Ytf3OQ2AAAAgPan1S+raaju3btn8uTJueaaa3LIIYekX79+6dKlSwYMGJDPfOYzue++++pclgMAAACUV01RFEVLd6I9mDt3bgYMGJAkmTNnTvr379/CPQIAAID2pxrfv9vNmSMAAAAAm0I4AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASq3ZwpEXX3wx48ePz+DBg9OjR4/06dMnw4cPzwUXXJAlS5Y0SRsvvPBCzjzzzOy9997p3bt3OnfunD59+uQDH/hAvvvd7+aVV15pknYAAACA9qOmKIqi2o3ceuutOfbYY7Nw4cJa9w8aNCiTJ0/OwIEDN7mNq6++OuPGjcvSpUvrLNOnT59cd911OeSQQza5nbrMnTs3AwYMSJLMmTMn/fv3b/I2AAAAoOyq8f276meOzJw5M8ccc0wWLlyYnj175pxzzsn999+fKVOm5KSTTkqSPPPMMzn88MPz1ltvbVIb06dPz9ixY7N06dJ06NAhJ5xwQm666abMmDEjv/rVrzJmzJgkyeuvv54jjzwyf/3rX5vs+QEAAABtW9XDkdNOOy1Lly5Np06dctddd2XChAnZd999c9BBB+XSSy/N+eefn+TtgOTCCy/cpDbOPffcrFmzJkny4x//OD//+c9z5JFHZvjw4fnEJz6RW265JV/72teSJEuXLs3//b//t2meHAAAANDmVXVZzYwZM7LPPvskScaNG5ef/exnG5RZs2ZN3v3ud2fWrFnp3bt3XnnllXTu3LlR7fTp0ydvvPFG+vbtm/nz59da5s0330zv3r2TJO973/vy6KOPNu7J1MOyGgAAAKi+Nres5qabbqpsn3DCCbV3oEOHHHfccUmSBQsWZOrUqY1uZ8WKFUmSXXfdtc4yvXr1yjbbbLNeeQAAAICqhiP33XdfkqRHjx7Ze++96yx3wAEHVLanT5/e6Hb22GOPJMnzzz9fZ5mFCxdWzipZWx4AAACgquHIrFmzkiQDBw5Mp06d6iw3ePDgDR7TGCeffHKS5LXXXqt16U6S/Md//McG5Rtj7ty5G/2ZN29eo+sEAAAAWl7dicVmWrZsWeVMjfrW/2y99dbp0aNHFi9enDlz5jS6rc9//vO57777ctVVV+XUU0/No48+miOOOCI77LBDXnrppVx99dWVJT7//u//noMPPrjRbaxdzwQAAAC0L1ULR9a9LW/Pnj3rLb82HFm0aFGj2+rYsWOuvPLKjBkzJt///vdz2WWX5bLLLluvzKhRozJhwoRNCkYAAACA9quqZ46s1aVLl3rLd+3aNcnbt9rdFLNmzcpVV12VJ554otb9DzzwQCZNmpQhQ4bkHe94R6Prr++Mlnnz5mXEiBGNrhcAAABoWVULR7p161bZbsjdYZYvX54k6d69e6PbmjZtWsaMGZM333wzO++8c773ve/lkEMOSZ8+ffLyyy/nlltuybe//e1cd911uffee3PXXXflXe96V6PacGteAAAAaJ+qdkHWLbfcsrLdkKUyixcvTtKwJTjrWr58eT796U/nzTffzPbbb58HH3wwxx57bLbbbrt07tw5/fv3zymnnJJ777033bp1y9///vccf/zxjXsyAAAAQLtVtXCkW7du6du3b5K37/SyMW+88UYlHGnshU/vvPPO/O1vf0uSfOUrX8n2229fa7l3vetdOfbYY5Mkjz76aP70pz81qh0AAACgfarqrXz33HPPJMns2bOzatWqOss99dRTle0hQ4Y0qo11b/37vve9b6Nl995771rbBAAAAMqrquHIfvvtl+TtJTOPPvponeXuueeeyvbIkSMb1UanTv/vsikbC2CSZOXKlbU+DgAAACivqoYjH/vYxyrbl19+ea1l1qxZk6uuuipJ0rt374waNapRbey6666V7WnTpm207LohzLqPAwAAAMqrquHIiBEjsv/++ydJJk2alAceeGCDMhdeeGFlacxpp52Wzp07r7f/7rvvTk1NTWpqajJ27NgNHv+hD30oW2yxRZLkpz/9aZ238r3jjjvym9/8Jknyjne8I+9973s39WkBAAAA7UhVw5Ekufjii9O9e/esWrUqo0ePzrnnnpsH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eCL/8i//0uB2muK+yQAAAEDrU7VlNVtuuWVluyFLZdaeAdKQJTh1tbPttttm6NChdZb98Ic/XNl++OGHG9UOAAAA0D5VLRzp1q1b+vbtm6T+O7288cYblXCksRc+Xbd8fWd3rFv21VdfbVQ7AAAAQPtUtXAkSfbcc88kyezZs7Nq1ao6yz311FOV7SFDhjSqjXe9612V7dWrV2+07Lr7N3ZrYQAAAKA8qhqO7LfffkneXjLz6KOP1lnunnvuqWyPHDmyUW3svPPO2WmnnZIkL7zwQoqiqLPsc889V9l+xzve0ah2AAAAgPapquHIxz72scr25ZdfXmuZNWvW5KqrrkqS9O7dO6NGjWp0O5/4xCeSJAsXLsyUKVPqLPfrX/+6sr02uAEAAADKrarhyIgRI7L//vsnSSZNmpQHHnhggzIXXnhhZs2alSQ57bTT0rlz5/X233333ampqUlNTU3Gjh1baztf/epXK3et+drXvpaFCxduUOYXv/hF7r777iTJ4Ycf3uhrmwAAAADtU1XDkSS5+OKL071796xatSqjR4/OueeemwcffDBTp07NuHHjcsYZZyRJBg0alPHjx29SGzvttFO++93vJkmeeOKJjBgxIpdffnkeffTRTJ06NV/5ylcqwcpWW22Viy66qEmeGwAAAND2Vf2qpEOHDs3111+fY489NgsXLsyECRM2KDNo0KBMnjx5vdvyNtbXv/71vP766znvvPPy9NNP5/Of//wGZfr165ebbropu++++ya3AwAAALQvVT9zJEnGjBmTxx9/PKeffnoGDRqULbbYIr17986wYcNy3nnnZebMmRk4cOBmt3Puuedm+vTp+dznPpdddtklXbt2Ta9evTJ8+PD8x3/8R5555pnsu+++TfCMAAAAgPaiptjY7V1osLlz51auYzJnzpz079+/hXsEAAAA7U81vn83y5kjAAAAAK2VcAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEIAAAAUGrCEQAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAoNeEI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NEly2WWX5Vvf+tbmPykAAACg3aj6mSMf/OAHM23atHTq1Cn33ntv9t133/X2X3DBBTnjjDOSJGeddVbOPvvsRrfxzDPP5F3veldWrVqVYcOG5d5770337t0r+5csWZIDDjggjzzySDp16pRZs2Zt1lkqtXHmCAAAAFRfmztzZMaMGZk2bVqS5Atf+MIGwUiSjB8/PkOGDEmSXHzxxVm5cmWj2/nRj36UVatWJUl+/OMfrxeMJMkWW2yRH//4x0mSVatW5aKLLmp0GwAAAED7VNVw5Kabbqpsn3DCCbV3oEOHHHfccUmSBQsWZOrUqY1qoyiK3HzzzUmSwYMH5/3vf3+t5d7//vdnjz32SJLcfPPNaYZLrQAAAABtQKdqVn7fffclSXr06JG99967znIHHHBAZXv69OkZPXp0g9t4/vnn8/e//32Deupq5+mnn87f/va3vPDCC9l1110b3E57s6ZYkwXLF7R0NwAAAGhFenftnQ41zXZj21ajquHIrFmzkiQDBw5Mp051NzV48OANHtNQTz75ZK31NKSdxoQjc+fO3ej+efPmNbiu1mDB8gU54PqNh0kAAACUyz3H3JM+3fq0dDeaXdXCkWXLlmX+/PlJUu/FUbbeeuv06NEjixcvzpw5cxrVzrqhRX3trL1gS5JGt7PuYwEAAID2o2rnyqx7W96ePXvWW75Hjx5JkkWLFlWtnbVtbEo7AAAAQPtU1TNH1urSpUu95bt27ZokWbp0adXaWdvGprRT35km8+bNy4gRIxpVJwAAANDyqhaOdOvWrbK9YsWKessvX748STa4DW9TtrO2jU1ppynum9ya9O7aO/ccc09LdwMAAIBWpHfX3i3dhRZRtXBkyy23rGw3ZAnL4sWLkzRsCc6mtrO2jU1pp73pUNOhlBfZAQAAgH9WtWuOdOvWLX379k1S/51e3njjjUpw0dgLn657Rkd97ay7NMYFVgEAAICkiuFIkuy5555JktmzZ2fVqlV1lnvqqacq20OGDNmkNv65nqZuBwAAAGifqhqO7LfffkneXs7y6KOP1lnunnv+37UvRo4c2ag2dt111+y4444b1FObe++9N0nyjne8I7vsskuj2gEAAADap6qGIx/72Mcq25dffnmtZdasWZOrrroqSdK7d++MGjWqUW3U1NTkyCOPTPL2mSEPPvhgreUefPDBypkjRx55ZGpqahrVDgAAANA+VTUcGTFiRPbff/8kyaRJk/LAAw9sUObCCy/MrFmzkiSnnXZaOnfuvN7+u+++OzU1NampqcnYsWNrbeerX/1qOnbsmCT5yle+ssFtepcuXZqvfOUrSZJOnTrlq1/96uY8LQAAAKAdqWo4kiQXX3xxunfvnlWrVmX06NE599xz8+CDD2bq1KkZN25czjjjjCTJoEGDMn78+E1qY9CgQfn617+eJHnkkUcycuTIXH/99XnkkUdy/fXXZ+TIkXnkkUeSJF//+tez++67N82TAwAAANq8qt3Kd62hQ4fm+uuvz7HHHpuFCxdmwoQJG5QZNGhQJk+evN5teRvrnHPOySuvvJKf//znmTlzZj71qU9tUOYLX/hCvve9721yGwAAAED7U/UzR5JkzJgxefzxx3P66adn0KBB2WKLLdK7d+8MGzYs5513XmbOnJmBAwduVhsdOnTIpEmTMnny5Bx55JHZcccd06VLl+y444458sgjc/vtt+eyyy5Lhw7N8pQBAACANqKmKIqipTvRHsydOzcDBgxIksyZMyf9+/dv4R4BAABA+1ON799OowAAAABKTTgCAAAAlJpwBAAAACg14QgAAABQasIRAAAAoNSEIwAAAECpCUcAAACAUhOOAAAAAKUmHAEAAABKTTgCAAAAlJpwBAAAACg14QgAAABQasIRAAAAoNSEIwAAAECpCUcAAACAUhOOAAAAAKUmHAEAAABKTTgCAAAAlJpwBAAAACi1Ti3dgfZi1apVle158+a1YE8AAACg/Vr3O/e638U3h3Ckibz66quV7REjRrRgTwAAAKAcXn311eyyyy6bXY9lNQAAAECp1RRFUbR0J9qDZcuW5YknnkiSbLvttunUqfWflDNv3rzKWS4zZszIDjvs0MI9orGMYdtm/No+Y9j2GcO2zxi2bcav7TOGbV9bHMNVq1ZVVm/stdde6dat22bX2fq/wbcR3bp1y/Dhw1u6G5tshx12SP/+/Vu6G2wGY9i2Gb+2zxi2fcaw7TOGbZvxa/uMYdvXlsawKZbSrMuyGgAAAKDUhCMAAABAqQlHAAAAgFITjgAAAAClJhwBAAAASk04AgAAAJSacAQAAAAotZqiKIqW7gQAAABAS3HmCAAAAFBqwhEAAACg1IQjAAAAQKkJRwAAAIBSE44AAAAApSYcAQAAAEpNOAIAAACUmnAEAAAAKDXhCAAAAFBqwhEAAACg1IQjbdyiRYty77335oc//GGOPvro7LrrrqmpqUlNTU122WWXqrR5//3359hjj83OO++cbt26Zfvtt8+HP/zhXHvttY2q59prr83o0aOz/fbbp1u3btl5551z7LHH5oEHHqhKv1u7JUuW5Pzzz8/w4cPTp0+f9OjRI4MHD8748ePz4osvbnb9u+yyS+V3o6E/L7zwwgb1nH322Q1+/N13373Z/W5Lqj2GL7zwQoOP/dixYxtUp3m4vmqP4Zo1a3LvvfdmwoQJOfDAA7P99tunS5cu2WqrrfLud787p5xySh5//PF66ynbPHzxxRczfvz4DB48OD169EifPn0yfPjwXHDBBVmyZEmTtXPHHXfkqKOOSv/+/dO1a9f0798/Rx11VO64444G17Fq1ar87Gc/y/77759tt9023bt3z2677ZZx48blL3/5S5P1tS2p5vgtWbIkv/71r/OlL30pw4cPz9Zbb53OnTunb9++2XfffXP22WfnH//4R731HHjggQ2eU2VUzTG84oorGnzsr7jiinrrq/breFtVrTFszGeT+r6jmIcbeuWVV3Lbbbdl4sSJOfTQQ7PNNts0+rNeYzXFZ8M2Ow8L2rQDDzywSFLrz84779zk7Z111llFhw4d6mzz8MMPL5YuXbrROpYsWVIcdthhddbRoUOH4uyzz27yvrdmzz77bLH77rvXeUy22mqr4tZbb92sNnbeeec666/tp1evXrWO5VlnndXgOqZOnbpZfW5LmmMMn3/++QYf++OPP36jdZmHG2qOMRwwYEC9Y9ehQ4fijDPOKNasWVNnPWWah7fcckux1VZb1fn8Bg0aVDz77LOb1cbq1auLL3zhCxs9jieeeGKxevXqjdbz6quvFsOHD6+zjq5duxb/8z//s1l9bWuqOX5/+tOfip49e9Y7B7baaqviuuuu22hdBxxwQIPnVNlUew5efvnlDT72l19++Ubrao7X8baommPYmM8ma39Gjx5da13m4YY2dgzq+6zXWE312bAtz8Py/Ga1U+u+iPTp06cYPXp05YNCU4cjP/vZzypt7bbbbsWkSZOKGTNmFDfddFMxatSoyr5Pf/rTG63nU5/6VKXsqFGjiptuuqmYMWNGMWnSpGK33Xar7LvkkkuatP+t1cKFC4tBgwZVnvdJJ51UTJkypbj//vuLc845pzKeW2yxRTFz5sxNbufpp58unnjiiY3+XHTRRev1ozbrfimrr75FixZtcn/bkuYaw3U/gHzve9/b6LGfO3fuRusyD9fXXGPYsWPHIkkxcODA4swzzyxuueWW4pFHHimmTZtWfPe73y223nrrSh+++c1v1llPWebhY489VnTv3r1IUvTs2bM455xzivvvv7+YMmVKcdJJJ633wX7hwoWb3M43vvGNSl1Dhw4trr322mLGjBnFtddeWwwdOrRBY7Jq1apiv/32q5T9+Mc/Xtxxxx3FQw89VPznf/5n0a9fv8qHy9tvv32T+9qWVHv8pk2bVqlj5MiRxbnnnlv87ne/Kx577LHit7/9bTFu3LjKH3Q6duy40eO+9vPUsGHD6p1TZdIcc3DdcOS3v/3tRo/9G2+8UWc9zfU63tZUewxXrFhR75x54oknis985jOVtq655ppa6zIPN7RuqLDTTjsVo0ePrlo40hSfDdv6PBSOtHGXXHJJ8ctf/nK9tHftGQJNGY689tprRa9evSoT89VXX11v/6pVq4oxY8ZUJkJdf6mcMmVKpcyYMWOKVatWrbf/1VdfLXbaaaciSdG7d+/i9ddfb7Ln0Fp9+9vfrhyT888/f4P906dPLzp16lQkKQ444ICq9uXoo4+u9GXatGm1lln3Sxlva64xXDccqe+vZxtjHm6oucZw3333Le688846zwqZPXt2se222xZJik6dOhXPPfdcreXKMg/333//yrG4//77N9h//vnnV47DWWedtUltPP3005WxHTZsWLFkyZL19i9evLgYNmxYpR91/XV10qRJlb6ccsopG+x/9tlnK3+5HThwYLFy5cpN6m9bUu3xmz59enH00UcXf/nLX+osc9NNNxU1NTWVP+zUNffWfimr9vtsW9Mcc3DdcOT555/f5L62ps9TrUlzjGF9Vq1aVey4445FkmLLLbfc4HV2LfNwQxMnTixuvfXW4h//+EdRFOt/FmzKcKSpPhu29XnYvj9VlVQ1wpHzzjuv8ot+7bXX1lpmzpw5lb+KHnbYYbWWOfTQQysv0HPmzKm1zLXXXrvRSdWerFixohI6DRkypM5TtseNG1c5JjNmzKhKXxYsWFB069atSFK8853vrLNcWb6UNVRzjmFThSPm4fpa0zwsiqL48Y9/XGnnwgsvrLVMGebhQw89VHmO48aNq7XM6tWriyFDhlQ+rK1YsaLR7XzpS1+qtPPAAw/UWuaBBx7YaPBRFEWlH3369CkWL15ca5lzzz23Us8NN9zQ6L62Jc01fg3xiU98otKXRx99tNYyvpRtqLnGsCnCkdb2Ot5atJZ5eOedd1b6ccIJJ9RZzjysX7XCkab4bNge5qELstIgN910U5Jkq622ysc//vFay/Tv3z8HH3xwkmTKlCl566231tv/1ltvZcqUKUmSgw8+OP3796+1no9//OPZaqutkiS/+c1vmqL7rdbUqVPz5ptvJkmOP/74dOhQ+5Rc94JL1TomN9xwQ5YtW5YkOe6446rSRnvUmsawIczDDbW2MRw1alRl+7nnnqtaO63d2vedJDnhhBNqLdOhQ4fK69WCBQsyderURrVRFEVuvvnmJMngwYPz/ve/v9Zy73//+7PHHnskSW6++eYURbHe/meeeSazZs1Kkhx99NHZYostaq2ntbwONIfmGL+GMqc2TWsaw/q0ttfx1qK1jOFVV11V2T7++OObvH42T1N9NmwP81A4Qr1WrFiRGTNmJEn23XffdOnSpc6yBxxwQJJk+fLleeSRR9bb9/DDD2fFihXrlatNly5dKh9QH3744axcuXKz+t+a3XfffZXtjR2TYcOGVT5sT58+vSp9WfvGVVNTk8997nNVaaM9ak1j2BDm4YZa2xguX768st2xY8eqtdParR2XHj16ZO+9966z3Lpj1thxef755/P3v/99g3o21s7f/va3De7k1dDfoe233z6DBg3apL62Nc0xfg1lTm2a1jSG9Wltr+OtRWsYw7feeqsS0uyyyy754Ac/2KT1s/ma6rNhe5iHwhHq9cwzz2T16tVJ3v7L2sasu3/tX9HWevLJJ2stt7F6Vq1alWeffbZR/W1LGnpMOnXqlIEDBybZ8Lg2heeff77y4rTffvvlne98Z4MeN3r06PTr1y9dunRJv379cuCBB+YHP/hB3njjjSbvY2vVUmP44x//OAMHDky3bt3Sq1evvOtd78rJJ5+cxx57rEn6u+5+8/Bt1Z6Ha91zzz2V7SFDhtRbvr3Ow7XHeODAgenUqVOd5Tb2vlOfTZkPtbWzKfXMmTMnixcvbnBf25rmGL+Gasyceuqpp7LPPvukd+/e6datW/r3758jjzwyV111VbsOiWvTEmN4wgknZMcdd0yXLl2yzTbb5P3vf3++9a1v5W9/+9tGH9faXsdbi9YwD3/1q19VbhX8uc99rkG34TUPm1dTfTZsD/NQOEK95s6dW9mu6zSrtQYMGFDZnjNnTlXqaU/WHpMePXqkd+/eGy279pi8+uqr6/0VrClcddVVldPEG7Ok5ne/+11effXVrFy5Mq+++mruueeefPOb38w73/nOyqnq7V1LjeFjjz2W5557LsuXL8/ChQvz5JNP5pJLLsnee++dk08+uc76zcMNtZZ5mCRLlizJj370oyRJ165dc+SRR9b7mPY4D5ctW5b58+cnqf/3dOutt06PHj2SNP73tCXf34qiWO9x7UlzjV9D/OlPf8rkyZOTJHvttVe94cjLL7+cGTNm5M0338zy5cvzt7/9LbfcckuOP/74vPe97211H+SrpaXG8O677868efOycuXKvPbaa3nooYdyzjnnZODAgbnkkkvqfFxreh1vLVrLPFx3SU1DP2Oah82rqd8L2/I8rDtChP/futcO6dmz50bLrn1hTZJFixZVpZ72ZO0xqe94JBsek65duzZZP66++uokSffu3XP00UfXW36vvfbKxz72sYwYMSI77rhjVq5cmaeffjrXXHNN7rrrrixYsCCf+MQncuutt+bQQw9tsn62Rs09hr17985RRx2VAw88MLvvvnu6deuWefPm5a677sqkSZOyaNGiXHLJJXnrrbdyzTXX1NnfhvTZPNxQNedhkpx55pl56aWXkiSnnnpqdtxxxzrLtud52Jjf0+TtcVm8eHGjf0+9v1VHc41ffZYvX54TTzyxcvbrOeecU2fZDh065EMf+lAOO+ywvOc970nfvn3z1ltv5bHHHssll1ySWbNm5cknn8yoUaMyY8aM7LTTTk3a19amucfwne98Zz7+8Y9n3333rXxp+utf/5obb7wxv/rVr7Js2bKcfPLJqampyRe/+MU6+9saXsdbi9YwD1966aXKmVsf+MAHKmcL1MU8bBlN/V7YluehcIR6rb1IZ5KNXm8kyXq/2EuXLq1KPe3J2mNS3/FIqndM7r///soF6o488sjKhZbq8tWvfjVnn332Bv+/zz775Ljjjssll1ySk08+OatXr86JJ56Y5557Lt26dWuy/rY2zTmGO+64Y/72t79tcLHHoUOH5rDDDsupp56agw8+OC+99FJ++ctf5phjjskRRxxRa38b0mfzcEPVPCbXXHNN/uu//ivJ26f+f+9736uzbHufh435PU3+37g0dky8v1VHc41ffb785S9Xrn92/PHHZ8yYMXWW/fWvf13rXzr333//nHLKKTnppJNy5ZVX5uWXX85Xv/rV/PrXv27SvrY2zTmGRx11VI4//vgNllsMHz48xxxzTG677bZ8/OMfz8qVK3P66afniCOOyPbbb19rf1v6dbw1aQ3z8Be/+EWjzkw2D1tGU78XtuV5aFlNM6ipqdnsnyuuuKLF+r/uB+q1F+upy7qnRXXv3r0q9bSEao3h2mNS3/FIqndMGnsF8fpOkxs3bly+8IUvJEn+/ve/58Ybb9ys/jWV9jCGXbp0qfMuGEmy++675xe/+EXl3z/+8Y83KGMeXrFBva1hHt59992VedOnT5/ceOONG62/rc7DhmrM72ny/8alsWPi/a06mmv8Nubcc8/NZZddluTtL9k/+clPNlp+Y3Oqc+fOueyyyyp3LPrNb35T7zUw2rrmHMNevXpt9DoUH/3oRzNx4sQkby89nDRp0gZlWsPreGvTGubh2jOTu3btmmOOOabe8uZhy2jq98K2PA+FI9Rryy23rGzXd6rduheX++dTqpqqnvZk7TFpyCmM1Tgmy5cvzw033JAk2WGHHXLIIYc0Sb3jxo2rbK97Ibz2qKXH8J/tv//+2XPPPZO8fdXwNWvWrLffPNxQS4/hI488kiOOOCLLly9Pz549c/vttzfoQqz1acvzsDG/p8n/G5fGjon3t+porvGryyWXXJIJEyYkefuigLfffvt6p3Bvik6dOlUCx6TtzanGaukx/Gdf/OIXKwFKbce+pV/HW6OWHsMZM2bkqaeeSpIcccQR9Yb6DVG2edhcmvq9sC3PQ8tqmkFTXDRohx12aIKebJp1L8xT38Xj1r0wz7oX7KmtnmHDhm1SPS2hWmPYv3//PPTQQ1m8eHEWLFiw0TeOtcdk2223bbJ1ebfeemvljhaf+cxnmuwWh2u/nCdpNal+ex3D2uy555558skns2zZsrz22mvZdttt1+vvWubh21pyDP/yl7/kIx/5SN5666107do1N910U/bZZ5/NrjdpnfOwobp165a+ffvmtddeq/d954033qh8yGrs72m13t+22Wabeuupqamp98J3bVVzjV9trr322pxyyilJkp133jm/+93vNjoejdGW51RjteQY1qZfv37p27dv5s+fX+uxb43vxS2tpcdwUy7E2hBlmofNpak+G7aHeSgcaQb13RKptRs0aFA6duyY1atXVxLguqy7/5//8rnui1lD6+nUqVN23333xna5yVVrDPfcc8/K6e5PPfVU5d7h/2zVqlWV64I0xV+U12rskpqGasht2ppbex3D2mzs+JuHG2qpMXzuuedyyCGH5LXXXkunTp1y/fXX50Mf+tBm17tWa5yHjbHnnntm2rRpmT17dlatWlXnbSg39r7TkDZqq6ex7fxzPe9973vrrWfAgAGbfTZDa9Yc4/fPbrnllhx33HFZs2ZNdthhh0yZMqVJA6i2PqcaqyXGcGPqe29rbe/FrUFLjeHKlStz3XXXJXk72PrIRz6y2XWuVbZ52Bya6rNhe5iHltVQry5dumTEiBFJkgceeGCj68jWnt7WtWvXDVLH4cOHVy7Qs7HT4FasWJEHH3yw8pjOnTtvVv9bs/3226+yvbFj8sgjj1QS/ZEjRzZJ26+++mruvPPOJMl73/ve7LXXXk1Sb7L+fc43dreN9qAlx7Aua49/165d07dv3/X2mYcbaokxnDt3bg4++ODMmzcvHTp0yJVXXtmg2/Y2Rlufh2vHZfHixXn00UfrLLfumDV2XHbdddfKsanv9Ox77703SfKOd7wju+yyS619ra+ef/zjH3nmmWc2qa9tTXOM37qmTJmSo48+OqtWrUrfvn3zu9/9Lrvtttsm11ebtj6nGqu5x3BjXn311cptaWs79q3xvbg1aKkxnDx5cl577bUkb5+ZXFcosynKNg+bQ1N9NmwX87Cg3dl5552LJMXOO+/cZHWed955RZIiSXHttdfWWmbOnDlFx44diyTFYYcdVmuZQw89tEhSdOrUqZgzZ06tZa699tpKW+eff36TPYfWaPny5UWvXr2KJMWQIUOKNWvW1Fpu3LhxlWMyY8aMJmn74osvrtR50UUXNUmda5144omVuq+++uomrbu1ackxrM19991XaedDH/pQrWXMw/U19xi+/PLLxR577FGp69JLL93kujamrc/Dhx56qNL/cePG1Vpm9erVxZAhQ4okRe/evYsVK1Y0up0vfelLlXYeeOCBWss88MADlTKnnHJKrWXW9qNPnz7F4sWLay1z7rnnVuq54YYbGt3XtqS5xq8oimL69OlFjx49iiRFr169ikceeWRzul6rlStXVvqapHjppZeavI3WpjnHsD7f+973Kn35j//4jw32t7b34taipcbwqKOOqrQ7c+bMza5vrTLOw3/2/PPPV57/8ccf32T1NsVnw/YwD4Uj7VBjw5F1J9kBBxxQa5nXXnut8su+8847F/Pnz19v/6pVq4oxY8ZU6pk6dWqt9UyZMqVS5ogjjihWrVq13v5XX3212GmnnSov0K+//nqDnkNb9u1vf3ujLzT3339/0alTp42OT1EUlToaOu5777135UXw5ZdfbtBjHn/88eLZZ5/daJlLLrmk0pftt9++WLRoUYPqbsuaawx/85vf1PlGUxRF8eyzz1bmT5LixhtvrLWcebih5hrDN954o3jve9+7WcFkmebh/vvvX3mduv/++zfYf/7551ee51lnnbXB/qlTp9b7IfLpp5+uBPvDhg0rlixZst7+JUuWFMOGDav045lnnqm1nkmTJlXaOvXUUzfYP3v27GKrrbYqkhQDBw4sVq5cWf8BaOOaY/xmzpxZ9O7du0hS9OjRo7jvvvsa3c8//OEPxRtvvFHn/hUrVhTHH398pS9jxoxpdBttVbXH8Pnnny8ee+yxjfbh1ltvLbp06VIkKbp3717MnTu31nJN9Tre3jTHPFzXa6+9Vhmvvfbaq8H9NA8bZlPCkcsvv3yjY1wUTffZsK3PQ+FIG/fss88Wl19++Xo/ffv2LZIUffv23WDfvHnzNqijIeFIURTFz372s0q53Xbbrfj5z39ePPzww8XNN99cjBo1qrLv05/+9Eb7/KlPfapSdtSoUcXNN99cPPzww8XPf/7zYrfddqvsu+SSSzb38LQJCxcuLAYNGlR53l/84heLP/zhD8UDDzxQfP/73y969uxZ+UCwsfS9MeHIX/7yl0r5j370ow3u6+WXX1507NixOPjgg4sLL7ywuOuuu4pHH320eOihh4orr7yyGD16dKXejh07FrfcckuD627LmmsM136pOuOMM4pf/epXxYMPPljMnDmzuP3224vTTjut0k6S4uijj95on83D9TXHGC5btqz4wAc+UCnz2c9+tnjiiSc2+vPXv/51g3rKNA8fe+yxonv37kWSomfPnsX3v//94oEHHij+8Ic/FF/84hcrz3PQoEHFwoULN3h8Qz/Uf+Mb36iUGzp0aHHdddcVDz/8cHHdddcVQ4cOrez75je/WWcdq1atKkaOHFkp+4lPfKK48847i4ceeqj48Y9/XPTr169IUnTo0KG4/fbbm+LwtHrVHr/Zs2dXjuvasLG+OVXbHwOOP/74omfPnsVnPvOZ4tJLLy3uueeeYubMmcW0adOKH/3oR8Wee+5ZaaNfv361zsv2qtpjuHb/vvvuW3z/+98vJk+eXDz88MPFww8/XFx//fXFv/7rvxY1NTWVOn7yk5/U2demeh1vb5rrdXStn/zkJ5XyP/zhDxvcT/OwdtOmTVvvu9wFF1xQOQ4jR47c4LtebRoSjhRF03w2bOvzUDjSxq37y96Qn9rO6GhoOFIURTFx4sT13qT++eewww4rli5dutE6lixZUhx22GF11tGhQ4eNTtz26Nlnny123333Oo/JVlttVdx6660braMx4ciZZ55ZKd+YU7sb+vvWt2/f4qabbmpwve1Bc4xhQ+f5l770pWLZsmUbbcs83FC1x3Dd19qG/tT2mly2eXjLLbdUzrio7WfQoEF1nknT0A/1q1evLj7/+c9v9Hh+4QtfKFavXr3Rvr766qvF8OHD66yja9euxf/8z/9szuFoc6o5fo39DJTU/sVg3b9Gb+xnr732Kv7yl7808RFq/ao5huvu39jPFlts0aCwvilex9uj5ngdXWufffYpkrfD+dr+KFsX87B2DT0ua39q09BwpKk+G7bleSgcaeOaOxwpirfX9n7mM58pBgwYUHTp0qXo169fccghhxS//OUvG9X3a665pjjkkEOKfv36FV26dCkGDBhQfOYzn6n1lL8yWLRoUXHeeecVw4YNK3r37l1sscUWxR577FGcfvrpxQsvvFDv49eOYX3hyOrVq4v+/fsXydunxdX3JXpdL7/8cjFp0qTixBNPLPbee++if//+Rffu3Ytu3boVO+64Y3HooYcWF198cfHmm282uM72pNpjeMsttxTf/OY3i4MOOqjYbbfdil69ehWdOnUq+vTpUwwbNqw4/fTTiyeeeKJRfTYP11fNMWyqcKSM8/CFF14oTj/99GLQoEHFFltsUfTu3bsYNmxYcd5559V5fY+iaPyH+smTJxdHHnlkseOOOxZdunQpdtxxx+LII49s1JkeK1euLP77v/+72G+//Yq+ffsW3bp1K975zncWJ510UvHnP/+5wfW0J9Uav6YKR5588snioosuKo4++uji3e9+d7HddtsVnTt3Lnr27FnstttuxTHHHFP87//+7wanmZdJtcZw4cKFxS9+8Yvi1FNPLfbZZ59ip512KrbYYouiS5cuxXbbbVccdNBBxTnnnNPg5b9Fsfmv4+1Vc7yOPvPMM5WyH/nIRxrVP/Owds0ZjqzVFJ8N2+o8rCmKoggAAABASbmVLwAAAFBqwhEAAACg1IQjAAAAQKkJRwAAAIBSE44AAAAApSYcAQAAAEpNOAIAAACUmnAEAAAAKDXhCAAAAFBqwhEAAACg1IQjAAAAQKkJRwAAAIBSE44AAAAApSYcAQAAAEpNOAIAAACUmnAEAAAAKDXhCAAAAFBqwhEAAACg1IQjAAAAQKkJRwAAAIBSE44AAAAApSYcAQAAAEpNOAIAAACUmnAEAAAAKLX/D8B8k7CpodaOAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 428, + "width": 547 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = balance_base\n", + "for before_mix, rows in df.groupby(df['before_mix']):\n", + " plt.plot(rows['action_mix'], rows['after_profit'])" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "8d86eaa5-af35-4622-b4fe-d739949642d5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Unnamed: 0actionaction_mixpre_vaultpre_pool_0pre_pool_1before_vaultbefore_pool_0before_pool_1after_vaultafter_pool_0after_pool_1pre_mixbefore_mixafter_mixbefore_profitafter_profit
00deposit1.02567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848980.4714220.4714220.47142200
11deposit1.02567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848980.4714220.4714220.47142200
22deposit1.02567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848980.4714220.4714220.47142200
33deposit1.02567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848980.4714220.4714220.47142200
44deposit1.02567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848982567845171597953132312712941135651417606770004145101514458547777848980.4714220.4714220.47142200
......................................................
100100deposit1.0256784517159795313231271294113565141760677000414510151445854777784898256785825837777307515511018427127993527540071517510151445854777784898256787127737677450718417459403172901184222065205101514458547777848980.4714220.3677370.266697130867798199428424130189990014320290
101101deposit1.0256784517159795313231271294113565141760677000414510151445854777784898256785825837777307515511018427127993527540071517510151445854777784898256787127737677450718417459403172901184222065205101514458547777848980.4714220.3677370.266697130867798199428424130189990014320290
102102deposit1.0256784517159795313231271294113565141760677000414510151445854777784898256785825837777307515511018427127993527540071517510151445854777784898256787127737677450718417459403172901184222065205101514458547777848980.4714220.3677370.266697130867798199428424130189990014320290
103103deposit1.0256784517159795313231271294113565141760677000414510151445854777784898256785825837777307515511018427127993527540071517510151445854777784898256787127737677450718417459403172901184222065205101514458547777848980.4714220.3677370.266697130867798199428424130189990014320290
104104deposit1.0256784517159795313231271294113565141760677000414510151445854777784898256785825837777307515511018427127993527540071517510151445854777784898256787127737677450718417459403172901184222065205101514458547777848980.4714220.3677370.266697130867798199428424130189990014320290
\n", + "

105 rows × 17 columns

\n", + "
" + ], + "text/plain": [ + " Unnamed: 0 action action_mix pre_vault \\\n", + "0 0 deposit 1.0 25678451715979531323127 \n", + "1 1 deposit 1.0 25678451715979531323127 \n", + "2 2 deposit 1.0 25678451715979531323127 \n", + "3 3 deposit 1.0 25678451715979531323127 \n", + "4 4 deposit 1.0 25678451715979531323127 \n", + ".. ... ... ... ... \n", + "100 100 deposit 1.0 25678451715979531323127 \n", + "101 101 deposit 1.0 25678451715979531323127 \n", + "102 102 deposit 1.0 25678451715979531323127 \n", + "103 103 deposit 1.0 25678451715979531323127 \n", + "104 104 deposit 1.0 25678451715979531323127 \n", + "\n", + " pre_pool_0 pre_pool_1 \\\n", + "0 12941135651417606770004 14510151445854777784898 \n", + "1 12941135651417606770004 14510151445854777784898 \n", + "2 12941135651417606770004 14510151445854777784898 \n", + "3 12941135651417606770004 14510151445854777784898 \n", + "4 12941135651417606770004 14510151445854777784898 \n", + ".. ... ... \n", + "100 12941135651417606770004 14510151445854777784898 \n", + "101 12941135651417606770004 14510151445854777784898 \n", + "102 12941135651417606770004 14510151445854777784898 \n", + "103 12941135651417606770004 14510151445854777784898 \n", + "104 12941135651417606770004 14510151445854777784898 \n", + "\n", + " before_vault before_pool_0 \\\n", + "0 25678451715979531323127 12941135651417606770004 \n", + "1 25678451715979531323127 12941135651417606770004 \n", + "2 25678451715979531323127 12941135651417606770004 \n", + "3 25678451715979531323127 12941135651417606770004 \n", + "4 25678451715979531323127 12941135651417606770004 \n", + ".. ... ... \n", + "100 25678582583777730751551 10184271279935275400715 \n", + "101 25678582583777730751551 10184271279935275400715 \n", + "102 25678582583777730751551 10184271279935275400715 \n", + "103 25678582583777730751551 10184271279935275400715 \n", + "104 25678582583777730751551 10184271279935275400715 \n", + "\n", + " before_pool_1 after_vault \\\n", + "0 14510151445854777784898 25678451715979531323127 \n", + "1 14510151445854777784898 25678451715979531323127 \n", + "2 14510151445854777784898 25678451715979531323127 \n", + "3 14510151445854777784898 25678451715979531323127 \n", + "4 14510151445854777784898 25678451715979531323127 \n", + ".. ... ... \n", + "100 17510151445854777784898 25678712773767745071841 \n", + "101 17510151445854777784898 25678712773767745071841 \n", + "102 17510151445854777784898 25678712773767745071841 \n", + "103 17510151445854777784898 25678712773767745071841 \n", + "104 17510151445854777784898 25678712773767745071841 \n", + "\n", + " after_pool_0 after_pool_1 pre_mix before_mix \\\n", + "0 12941135651417606770004 14510151445854777784898 0.471422 0.471422 \n", + "1 12941135651417606770004 14510151445854777784898 0.471422 0.471422 \n", + "2 12941135651417606770004 14510151445854777784898 0.471422 0.471422 \n", + "3 12941135651417606770004 14510151445854777784898 0.471422 0.471422 \n", + "4 12941135651417606770004 14510151445854777784898 0.471422 0.471422 \n", + ".. ... ... ... ... \n", + "100 7459403172901184222065 20510151445854777784898 0.471422 0.367737 \n", + "101 7459403172901184222065 20510151445854777784898 0.471422 0.367737 \n", + "102 7459403172901184222065 20510151445854777784898 0.471422 0.367737 \n", + "103 7459403172901184222065 20510151445854777784898 0.471422 0.367737 \n", + "104 7459403172901184222065 20510151445854777784898 0.471422 0.367737 \n", + "\n", + " after_mix before_profit after_profit \n", + "0 0.471422 0 0 \n", + "1 0.471422 0 0 \n", + "2 0.471422 0 0 \n", + "3 0.471422 0 0 \n", + "4 0.471422 0 0 \n", + ".. ... ... ... \n", + "100 0.266697 130867798199428424 130189990014320290 \n", + "101 0.266697 130867798199428424 130189990014320290 \n", + "102 0.266697 130867798199428424 130189990014320290 \n", + "103 0.266697 130867798199428424 130189990014320290 \n", + "104 0.266697 130867798199428424 130189990014320290 \n", + "\n", + "[105 rows x 17 columns]" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "id": "6b1f355f-75e3-4fac-aa3b-25a422af148f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'Withdraw Profit')" + ] + }, + "execution_count": 118, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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r2dmZoYVK1bgX//6FwCgqKgI3333ndaxjXv1aFvudvToUU0voxUrVkAmk+kce/z4cVRWVgIARo4cCQsLC62P2Va1tbWQy+XYtm0bIiMjmxyfOXMmfv31V839Xbt2Yf/+/S1eV6VS4euvv8ajjz6q+bgaNHzOS0pK8M9//lMTf/755/HWW29BqVSKxvfo0QPbtm1DSEiI5tovvfRS6z9IIiKiTsLiEhEREelN4+JSeXk5Tp06JTp+5coVZGRkAECTgkfD/czMTFy+fFl07PTp0ygvL9f6OJ1NqVTivffe03nc3NwcCxYs0NyPi4trMkYQBHz99dea+6+++ipcXV11XnPlypXw9vZuc65LlixpU6+g1mjcEH3v3r1axzReunZrb6VbY3PmzEH//v1bNVafS+IA4P7778eYMWN0Hp80aRLuvvtuzf0vvviixWuOGDEC999/f7NjNm7ciLKyMgD1hcU33nhD51gzMzN89NFHmvvR0dFtavJORETUGVhcoi4rNzcXO3bswKuvvoo77rgDzs7Omp1JFi9e3Gl5qNVqxMfHY/369XjyyScREhICMzMzrTuvtMbOnTsxf/589O7dG5aWljA3N4enpyfuvPNObN68GWq1umM+ECKiTuDm5oagoCDN/Vt3f2t8/9bi0q19lxprfD8wMBA9evTQS77tMXbs2BYff8iQIZrbDbuHNZaQkIDr168DABQKBe67775mr2dqatriGG3mz5/f5nPUajVOnDiBL774Aq+99hqWLVuGJUuWaP41LoScPXtW6zWGDRum6bN05swZFBcXi443/O309vaGr6+vpmh07tw5UV+ixmMB/ReXFi5c2OKYxk20tRW/btWaz3njGVALFixocTbWiBEjMGDAgDblQURE1JnY0Ju6LDc3N6lTAAB89913eilmVVdX4/777xdNsW+QmZmJzMxMbNu2DR9//DG2bdumtaEpEZEhGDdunGZmRUxMDFasWKE5pq2Zd4PQ0FDNbnMxMTGi372Nz5Ny1hIA0Yt8XRo3OS4pKWly/MyZM5rbwcHBrfqdP3r06NYl+D+mpqatyrWBSqXCBx98gP/+97/IzMxs1Tn5+fla4wqFAqGhodi5cyfq6uoQExODmTNnAgAqKys1s7kals9FRETgww8/hCAIOHjwoKZxdHV1NY4dOwagfgZPWz8HzZHJZBg5cmSL4xo/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otdZWVmlcp7zKd4xVVx2dja7du2ievXqVK1aFXd3/dWUyunw4cNF3XsbNmwgPDzc5EQiZYuuEZGz0/Uhcna6PkROy8/PJzExEYArr7yyRM5ZaT/BW0rgUelff/0199577+WHuQTe3t5Fr09tyH02OTmnn8rh4+NTKuc5n/PdcgcQFRV13jUilUl4ePgFXTsilZWuEZGz0/Uhcna6PkQokVvhzqTb4sqpgICAotfnu0UtI+P0BqXFb30rqfOIiIiIiIiISOVUaTuXdu7cednnMLOV8sxK+8U8ia34xtrFz9OyZctLOo+IiIiIiIiIVE6VtrjUpEkTsyNclkaNGuHm5kZBQQG7du0659oz55s2bWqYO/OJbxd6Hnd3dxo2bHixkUVERERERESkAtJtceWUp6dn0YZ0a9euPed+SStWrAAKN+Qu3pnUqlWroo28T61zJjc3l3Xr1hUd4+HhcVn5RURERERERKRiUHGpHBs0aBAAqampTJ8+3emahIQElixZAkC3bt0MeyxB4Z5L3bp1A2DJkiVnvcVu+vTppKamAjB48OCSiC8iIiIiIiIiFYCKS2VUXFwcFosFi8VCly5dnK4ZMWIEQUFBAPz73//m+PHjhvmCggIefvhhCgoKAHjmmWecnufpp58GCh9H+MgjjxStPyUpKYlnn30WgODgYEaMGHHJfy4RERERERERqVgq7Z5LpSk6OppVq1YZxk49iS09PZ1vvvnGMNe7d29q1Khx0T8nJCSEd955hwcffJD9+/dz/fXX88ILL3DllVdy6NAhPvroI5YtWwbAHXfccdYi1Q033MDtt9/Ozz//zOzZs+nRowdjxoyhZs2abNu2jTfeeIP4+HgA3nnnHapUqXLRWUVERERERESkYrLY7Xa72SEqmm+++Yb77rvvgtcvW7bMofATFxdH/fr1AejcuTPLly8/6/GvvPIKr732Gmf7v7Jv375MmzYNb2/vs54jKyuLm2++mfnz5zudt1qtvPTSS7z66qvn/LOIiIiIiIiISOWi2+IqgP/85z+sWrWKoUOHUqdOHTw9PalWrRo9evTgxx9/ZN68eecsLAH4+Pgwb948Jk+eTI8ePahWrRqenp7UqVOHoUOHsmrVKhWWRERERERERMSBOpdEREREREREROSSqXNJREREREREREQumYpLIiIiIiIiIiJyyVRcEhERERERERGRS6bikoiIiIiIiIiIXDIVl0RERERERERE5JKpuCQiIiIiIiIiIpdMxSUREREREREREblkKi6JiIiIiIiIiMglU3FJRKQUbdq0if/+97/07NmT2rVr4+Xlhb+/P40aNeK+++5j1apVF3W+BQsWMHjw4KJz1a5dm8GDB7NgwYJS+hOIuN6zzz6LxWIp+rV8+fLzHqNrQyq6+Ph4XnnlFVq2bEnVqlXx9vamTp06dOzYkZdffpl//vnnnMfrGpGKKjc3l4kTJ9KrVy/Cw8OL3ms1btyY++67jzVr1lzQeXSNiFwmu4iIlIqOHTvagfP+GjZsmD0nJ+ec5yooKLAPHz78nOcZMWKEvaCgwEV/OpHSsXXrVru7u7vh7/ayZcvOul7XhlQGn3zyid3Pz++cf89Hjx7t9FhdI1KRxcXF2Zs3b37e91qPPfaY3WazOT2HrhGRkqHOJRGRUnLo0CEAatasyejRo5k6dSobNmxg7dq1fPjhh9SqVQuA7777jnvvvfec53rhhReYNGkSANdccw0//fQTGzZs4KeffuKaa64BYOLEibz44oul9wcSKWU2m42RI0eSn59PtWrVLugYXRtS0b3++us8/vjjZGRk0KhRI9577z2WL1/O1q1bWbJkCe+99x7t2rXDanX+tl7XiFRUeXl59OvXj+3btwNw1VVX8c0337B27VoWLVrEyy+/jJ+fHwCffvop77zzjtPz6BoRKSFmV7dERCqqfv362X/55Rd7fn6+0/nExER7o0aNir4VW7FihdN1u3fvLurkaNmypT0zM9Mwn5GRYW/ZsqUdsLu7u9v37t1b4n8WEVcYO3asHbA3adLE/txzz523c0nXhlR0S5YsMXS55ubmnnWtsw5YXSNSkU2ZMqXo+mjbtq3T91ubNm2ye3h42AF7cHCwPS8vzzCva0Sk5KhzSUSklMydO5dbb70VNzc3p/NhYWF88MEHRb+fOnWq03UfffQR+fn5QOE3bz4+PoZ5X19fPv30UwDy8/MZO3ZsScQXcan4+HheeuklAL744gs8PT3Pe4yuDanIbDYbDz30EABXX301kyZNwsPD46zrnV0zukakIjtzL6XnnnvO6fut6667jv79+wNw8uRJdu7caZjXNSJSclRcEhExUdeuXYtex8TEOMzb7XZmzZoFQJMmTWjTpo3T87Rp04bGjRsDMGvWLOx2eymkFSk9jzzyCOnp6dxzzz107tz5vOt1bUhFt2jRIvbu3QsUbnLv7u5+UcfrGpGKLjc3t+h1gwYNzrouMjLS6TG6RkRKlopLIiImysnJKXrt7Bu3ffv2Fe3ddL4P3KfmDx48SFxcXMmFFCllv/76K3PnziUkJIT333//go7RtSEV3ZQpUwCwWCxFnRcAycnJ7N27l+Tk5HMer2tEKrpTBR+A2NjYs6479eWdxWKhYcOGReO6RkRKlopLIiImWrFiRdHrpk2bOszv2LGj6HWTJk3Oea4z54u3fYuUVSdPnmT06NEAvPPOO4SFhV3Qcbo2pKJbt24dABEREQQEBPDjjz9y5ZVXEhoaSqNGjQgNDaVx48a8//77hi8qTtE1IhXdHXfcQWBgIFD434+CggKHNVu3bmXevHkADB06tGg96BoRKWkqLomImMRms/H2228X/f7WW291WJOQkFD0unbt2uc8X506dYpeHzhwoAQSipS+f/3rXxw5coT27dszfPjwCz5O14ZUZDabjV27dgGF+/ONHj2aO++8k3/++cewbs+ePTzzzDPccMMNnDx50jCna0QqurCwML7//nt8fX1ZvXo1rVq14rvvvmPdunUsWbKE//znP3Tu3Jnc3FyuvfZawz6XoGtEpKSpuCQiYpKxY8eyYcMGAIYMGcJ1113nsCYtLa3otb+//znPd+pxuwDp6ekllFKk9KxcuZKJEyfi7u7OF198gcViueBjdW1IRZaSkoLNZgNg27ZtfPLJJ4SHh/PDDz+QnJxMZmYmK1asKNojZs2aNdx///2Gc+gakcrgxhtvZPPmzYwYMYI///yTe+65h7Zt29KjRw9effVVfH19+eijj1i5ciXVq1c3HKtrRKRkqbgkImKCFStW8O9//xuAatWq8fnnnztdl52dXfT6fE/P8vLyKnqdlZVVAilFSk9ubi4jR47EbrfzxBNPcMUVV1zU8bo2pCLLyMgoep2dnY2vry/Lli3jzjvvpEqVKvj4+NCpUyeWLl3K1VdfDcCMGTNYv3694bhTdI1IRZWbm8t333131o22jx49yg8//MCSJUsc5nSNiJQsFZdERFxs+/btDB48mPz8fLy9vZkyZQrVqlVzutbb27vo9ZlPOHHmzD03ij9KV6SsefPNN9m1axd169bllVdeuejjdW1IRXbm32+AESNGGDYvPsXHx4c33nij6Pe//PKL03PoGpGKKCMjg+7du/PWW2+RnJzMv/71L3bu3ElOTg4pKSksWrSIDh06sGnTJgYNGsSHH35oOF7XiEjJUnFJRMSF9u3bR8+ePTlx4gRubm78/PPPdOrU6azrAwICil6frw37zG+6z9feLWKmXbt28dZbbwHw6aefGm43uFC6NqQiO/PvN0DPnj3PurZbt264u7sDsHHjRqfn0DUiFdGrr77KypUrAZg0aRLvvPMOTZo0wdPTk8DAQHr06MGyZcvo2rUrdrudZ555hr/++qvoeF0jIiXL3ewAIiKVxaFDh+jevTuHDh3CYrHw1VdfMXDgwHMec+YGk2duPOnMmRtMnrnxpEhZM3bsWHJzc2nQoAGZmZn8/PPPDmvO3Lh46dKlHDlyBIABAwbg5+ena0MqNC8vL6pWrUpiYiJw7r+33t7ehIWFceTIkaL1oP9+SMVmt9v56quvAGjUqBH33HOP03Xu7u689tprdOjQAZvNxjfffMPYsWMBXSMiJU3FJRERF0hKSqJHjx7ExsYChd0aw4YNO+9xzZo1K3p96slBZ3PmfNOmTS8xqUjpO3V7QWxsLHfcccd517/22mtFr/ft24efn5+uDanwmjdvzvLlywGcPmL9TKfmT3Uwgf77IRXb0aNHSU5OBuCaa64559ozH5hy5t91XSMiJUu3xYmIlLKUlBR69erFjh07AHj77bd55JFHLujY+vXrU7NmTaBwE/Bz+eOPPwCoVasWERERlx5YpBzQtSEV3Zm3TJ/6YsKZ1NRUkpKSgMK/46foGpGK7MxCan5+/jnX5uXlOT1O14hIyVJxSUSkFGVmZtKvXz+2bNkCwAsvvMCzzz57wcdbLJaiW+d27drFunXrnK5bt25d0bdqAwcOvKhHuou42jfffIPdbj/nrzM3+V62bFnR+Kk39bo2pKK76aabil7PmDHjrOtmzJhR9JSsjh07Fo3rGpGKLCQkhMDAQADWrl17zgLTmYWj+vXrF73WNSJSslRcEhEpJbm5uQwePJjVq1cDMHr0aF5//fWLPs+YMWNwc3MD4LHHHnN4BG5WVhaPPfYYUPiN3JgxYy4vuEg5oWtDKrKrrrqKPn36APDTTz/x+++/O6w5cuQIL774IlD4KPX77rvPMK9rRCoqq9VKv379gMI9Lc98auKZTpw4YfhSr3///oZ5XSMiJUfFJRGRUnLHHXewaNEiAG644QaGDx/OP//8c9Zfe/bscXqeRo0a8cwzzwCwadMm2rdvzy+//MKmTZv45ZdfaN++PZs2bQLgmWeeoWHDhq75A4qYTNeGVHQfffQRwcHB2Gw2+vfvz3PPPcfKlSvZtGkT48aNo1WrVkUbEb/22muG2+JA14hUbC+//DK+vr5A4ZPjbrzxRqZNm8bWrVtZu3YtY8eOpUWLFkXbEnTr1s3hyYu6RkRKjsV+qo9WRERK1MW2TderV4+4uDinczabjQceeKDoySjODB8+nAkTJmC16nsDKf9effVV/vOf/wCFt8V16dLF6TpdG1LRrVq1iptvvpmjR486nbdYLLzwwguGje/PpGtEKrIlS5Zwxx13FO07djY33HADU6dOpUqVKg5zukZESoaKSyIipaQki0unzJ8/nwkTJrBx40aSkpIICwujVatWjBo1quj2CZGK4EKLS6fo2pCK7Pjx43z66afMnDmTffv2kZubS3h4OF26dOGxxx4779OyQNeIVFzHjx9n0qRJLFiwgO3bt3Py5Enc3d2pUaMGrVq1YujQodx4443nfV+ma0Tk8qi4JCIiIiIiIiIil0x9fSIiIiIiIiIicslUXBIRERERERERkUum4pKIiIiIiIiIiFwyFZdEREREREREROSSqbgkIiIiIiIiIiKXTMUlERERERERERG5ZCouiYiIiIiIiIjIJVNxSURERERERERELpmKSyIiIiIiIiIicslUXBIRERERERERkUum4pKIiIiIiIiIiFwyFZdEREREREREROSSqbgkIiIiIiIiIiKXTMUlERERERERERG5ZCouiYiIiIiIiIjIJVNxSURERERERERELpmKSyIiIiJywSIiIrBYLNx7771mR3Fq+fLlWCwWLBYLy5cvNzuOiIhIpaDikoiIiIgLnFn0KP7L19eXevXqMWjQIH788Ufy8/PNjltq4uLiDH92q9XK/v37L+jYRo0aGY795ptvSjesiIiIXBAVl0RERERMlpWVRXx8PLNmzeLOO++kXbt2HDlyxOxYLmG325k8efJ5161bt469e/e6IJGIiIhcLBWXRERERFzsoYceYtu2bUW/1q5dy6effkpERAQAGzduZODAgdjtdnODljJvb28Avv/++/OuPbXm1DFn06VLF+x2O3a7nS5dulx2RhERETk/FZdEREREXKxatWpcccUVRb/atGnDo48+ypYtW4iKigJgw4YNzJ071+SkpevGG28EYNeuXWzatOms6/Ly8vjll18AGDhwoEuyiYiIyIVTcUlERESkjKhSpQrPPfdc0e8XLlxoYprS17RpU1q2bAmcu3tp/vz5HD9+HE9PT2677TZXxRMREZELpOKSiIiISBnSunXrotfONrpOTEzkxRdf5JprriE4OBhvb28iIiK4++67WbVq1QX9jLi4OJ544gmaN29OQEAAvr6+NGzYkFGjRrFt27YS+7NciLvvvhuAn3/++awbmX/33XcA9O/fnypVqpzzfOd6Wtybb75ZNPfuu++e9RybN2/G09MTi8VC165dsdlsF/EnEhERqXxUXBIREREpQzw8PIpeFxQUGOYWLVpEVFQUb7zxBn/++ScpKSnk5OSwf/9+fvjhBzp27Mijjz56zmLId999R5MmTfjoo4/YsWMH6enpZGVlER0dzYQJE7jmmmt46623Su3PV9ztt9+Ou7s7x44d47fffnOYP3HiBPPmzQNOF6Iu1b///W86duwIwEsvvcSff/7psCYzM5M777yTvLw8goOD+e6777Ba9ZZZRETkXPRfShEREZEy5MzOoZo1axa9/vPPPxkwYACpqal4eHjwxBNPsGzZMjZs2MD48eOpX78+AJ999pnh1rozzZs3j3vvvZecnBz8/f155ZVXWLlyJWvXruWDDz4gLCyMgoICnn/+eT7//PPS/YP+v2rVqtGrVy/A+a1xv/76Kzk5OYSGhtK3b9/L+llWq5Xvv/+eoKAgcnNzGTp0KFlZWYY1Tz75JLt37wbg888/p06dOpf1M0VERCoDFZdEREREyoj8/Hw++OCDot+f+bSzkSNHkpubi5ubG3PnzuXDDz+kS5cutGrVipEjR7J582aaNWsGwPvvv8/27dsN587Ly2PkyJHY7Xb8/f1ZuXIlr776Kh06dKBNmzY8+eSTbNq0ifDwcACefvppkpKSSv8PDQwbNgyA2bNnk5qaapg7VXC67bbb8PT8v/buLiSqLQzj+DNaM1qhKWZSoEkYGF1YmAkWelFCBX1ARjWZWZloQhDaF30gYUEWBZmgRhIWXVRUeBFERSJ9BwqGBYlikmRipREOozjnYpg5ymh1duOknv/vavbsvd537bvhYa015j/uFRUVpYsXL0qS3r59q4KCAve96upq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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 454, + "width": 587 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = withdraw_base\n", + "df = df[df.before_mix != df.after_mix]\n", + "\n", + "plt.title(\"Withdraw profit\")\n", + "plt.axhline(0, c=\"black\", linewidth=0.4)\n", + "for before_mix, rows in df.groupby(df['before_mix']):\n", + " plt.plot(rows['action_mix']*100, rows['after_profit'])\n", + "plt.ylim([-1e18,1e18])\n", + "plt.xlabel(\"Pool Mix\")\n", + "plt.ylabel(\"Withdraw Profit\")" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "id": "2dc420a4-af9d-4907-9a16-2de4ab697696", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-0.006252897237522348" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Unnamed: 0actionaction_mixpre_vaultpre_pool_0pre_pool_1before_vaultbefore_pool_0before_pool_1after_vaultafter_pool_0after_pool_1pre_mixbefore_mixafter_mixbefore_profitafter_profit
00withdrawall-2.002567845171597953132312712941135651417606770004145101514458547777848982567854631104364141628914941135651417606770004123514946002627038053612567905768457002526819213304229248305842309109109985960233166335352700.4714220.5474420.54743594595064110093162511373526383851903
11withdrawall-1.962567845171597953132312712941135651417606770004145101514458547777848982567854442443576167044514901135651417606770004123945361986613671630492567903134903041399934013268617699550024246809110369231382371761640880.4714220.5459160.54590992708456230347318486924594652328895
22withdrawall-1.922567845171597953132312712941135651417606770004145101514458547777848982567854253760679499434914861135651417606770004124375834323303772247002567900563073992759342013233006150794206184033110752552711789406338720.4714220.5443890.54438390821627263671222463093133132599071
33withdrawall-1.882567845171597953132312712941135651417606770004145101514458547777848982567854065055751186086514821135651417606770004124806362773929162692032567898052708326209240713197394602038388121565111135924008804131816420.4714220.5428640.54285788934577980537738439876525750231542
44withdrawall-1.842567845171597953132312712941135651417606770004145101514458547777848982567853876328864425302514781135651417606770004125236947106305104709602567895603551722404357913161783053282570058660111519345066663134344240.4714220.5413380.54133287047309112929898417272228579790554
......................................................
9696withdrawall1.842567845171597953132312712941135651417606770004145101514458547777848982567853210899954487453111247259132295014750407163501514458547774848982567916284622409599054210015310986173331542385145589395461373389093300.4714220.4075480.40755380393020013551404630737224551116011
9797withdrawall1.88256784517159795313231271294113565141760677000414510151445854777784898256785338523114689875911121053732693086154506916390151445854777784898256791901410060897630269982611437210358869418145945510948931572392010.4714220.4061690.40617482136331937664464656288694620775435
9898withdrawall1.92256784517159795313231271294113565141760677000414510151445854777784898256785355954315563219611117382009302296664502216430151445854777784898256792179777076366157969949915958977467906005146301626436489753013670.4714220.404790.40479683879452024998834682382276080293835
9999withdrawall1.96256784517159795313231271294113565141760677000414510151445854777784898256785373383590722417171113710745149115921188816470151445854777784898256792463588086606650999917224570103072238675146657741924047933641390.4714220.4034120.40341885622379540918590709020449588423382
100100withdrawall2.00256784517159795313231271294113565141760677000414510151445854777784898256785390810932534285871110039942373570360386816510151445854777784898256792752868460387925469884537289643397051952147013857411606114265850.4714220.4020350.40204187365113722105460736205752785363959
\n", + "

101 rows × 17 columns

\n", + "
" + ], + "text/plain": [ + " Unnamed: 0 action action_mix pre_vault \\\n", + "0 0 withdrawall -2.00 25678451715979531323127 \n", + "1 1 withdrawall -1.96 25678451715979531323127 \n", + "2 2 withdrawall -1.92 25678451715979531323127 \n", + "3 3 withdrawall -1.88 25678451715979531323127 \n", + "4 4 withdrawall -1.84 25678451715979531323127 \n", + ".. ... ... ... ... \n", + "96 96 withdrawall 1.84 25678451715979531323127 \n", + "97 97 withdrawall 1.88 25678451715979531323127 \n", + "98 98 withdrawall 1.92 25678451715979531323127 \n", + "99 99 withdrawall 1.96 25678451715979531323127 \n", + "100 100 withdrawall 2.00 25678451715979531323127 \n", + "\n", + " pre_pool_0 pre_pool_1 \\\n", + "0 12941135651417606770004 14510151445854777784898 \n", + "1 12941135651417606770004 14510151445854777784898 \n", + "2 12941135651417606770004 14510151445854777784898 \n", + "3 12941135651417606770004 14510151445854777784898 \n", + "4 12941135651417606770004 14510151445854777784898 \n", + ".. ... ... \n", + "96 12941135651417606770004 14510151445854777784898 \n", + "97 12941135651417606770004 14510151445854777784898 \n", + "98 12941135651417606770004 14510151445854777784898 \n", + "99 12941135651417606770004 14510151445854777784898 \n", + "100 12941135651417606770004 14510151445854777784898 \n", + "\n", + " before_vault before_pool_0 \\\n", + "0 25678546311043641416289 14941135651417606770004 \n", + "1 25678544424435761670445 14901135651417606770004 \n", + "2 25678542537606794994349 14861135651417606770004 \n", + "3 25678540650557511860865 14821135651417606770004 \n", + "4 25678538763288644253025 14781135651417606770004 \n", + ".. ... ... \n", + "96 25678532108999544874531 11247259132295014750407 \n", + "97 25678533852311468987591 11210537326930861545069 \n", + "98 25678535595431556321961 11173820093022966645022 \n", + "99 25678537338359072241717 11137107451491159211888 \n", + "100 25678539081093253428587 11100399423735703603868 \n", + "\n", + " before_pool_1 after_vault \\\n", + "0 12351494600262703805361 25679057684570025268192 \n", + "1 12394536198661367163049 25679031349030413999340 \n", + "2 12437583432330377224700 25679005630739927593420 \n", + "3 12480636277392916269203 25678980527083262092407 \n", + "4 12523694710630510470960 25678956035517224043579 \n", + ".. ... ... \n", + "96 16350151445854777484898 25679162846224095990542 \n", + "97 16390151445854777784898 25679190141006089763026 \n", + "98 16430151445854777784898 25679217977707636615796 \n", + "99 16470151445854777784898 25679246358808660665099 \n", + "100 16510151445854777784898 25679275286846038792546 \n", + "\n", + " after_pool_0 after_pool_1 pre_mix before_mix \\\n", + "0 13304229248305842309109 10998596023316633535270 0.471422 0.547442 \n", + "1 13268617699550024246809 11036923138237176164088 0.471422 0.545916 \n", + "2 13233006150794206184033 11075255271178940633872 0.471422 0.544389 \n", + "3 13197394602038388121565 11113592400880413181642 0.471422 0.542864 \n", + "4 13161783053282570058660 11151934506666313434424 0.471422 0.541338 \n", + ".. ... ... ... ... \n", + "96 10015310986173331542385 14558939546137338909330 0.471422 0.407548 \n", + "97 9982611437210358869418 14594551094893157239201 0.471422 0.406169 \n", + "98 9949915958977467906005 14630162643648975301367 0.471422 0.40479 \n", + "99 9917224570103072238675 14665774192404793364139 0.471422 0.403412 \n", + "100 9884537289643397051952 14701385741160611426585 0.471422 0.402035 \n", + "\n", + " after_mix before_profit after_profit \n", + "0 0.547435 94595064110093162 511373526383851903 \n", + "1 0.545909 92708456230347318 486924594652328895 \n", + "2 0.544383 90821627263671222 463093133132599071 \n", + "3 0.542857 88934577980537738 439876525750231542 \n", + "4 0.541332 87047309112929898 417272228579790554 \n", + ".. ... ... ... \n", + "96 0.407553 80393020013551404 630737224551116011 \n", + "97 0.406174 82136331937664464 656288694620775435 \n", + "98 0.404796 83879452024998834 682382276080293835 \n", + "99 0.403418 85622379540918590 709020449588423382 \n", + "100 0.402041 87365113722105460 736205752785363959 \n", + "\n", + "[101 rows x 17 columns]" + ] + }, + "execution_count": 116, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABFQAAAOACAYAAAAU9SfnAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAB7CAAAewgFu0HU+AADKQUlEQVR4nOzdd3iUZb7G8ftNL0CAEEJJCISOdKRXUbGDiGJbxb4LHHVXd3Xdou667trWhuvaRbCjYgEb0qT33iGEVEhCIAFC6rznD9aBN9TAZJ7JzPdzXbkO82Mmc++hSO48xbJt2xYAAAAAAADOWJDpAAAAAAAAADUNhQoAAAAAAEAVUagAAAAAAABUEYUKAAAAAABAFVGoAAAAAAAAVBGFCgAAAAAAQBVRqAAAAAAAAFQRhQoAAAAAAEAVUagAAAAAAABUEYUKAAAAAABAFVGoAAAAAAAAVBGFCgAAAAAAQBVRqAAAAAAAAFQRhQoAAAAAAEAVUagAAAAAAABUEYUKAAAAAABAFVGoAAAAAAAAVBGFCgAAAAAAQBVRqAAAAAAAAFQRhQoAAAAAAEAVUaj4kJycHE2bNk2PPvqoLrvsMjVo0ECWZcmyLN12221ey+FyubRx40ZNnDhR48aNU8+ePRUeHu7OMmfOnNN+jscff9z9/DP9ePzxx6v9fxsAAAAAAJ4QYjoAjoqPjzcdQZI0efJkrxY4v2jbtq3X3xMAAAAAgLNBoeKjmjVrpnbt2unHH3/0+nvbtu3+cWhoqDp16qSysjKtW7fujD/HuHHjdO21157yORUVFRo0aJAKCwtVp04dXX311WcbGQAAAAAAr6JQ8SGPPvqoevbsqZ49eyo+Pl6pqalq0aKF13N06NBBL7/8snr27KmuXbsqIiJCjz/+eJUKlYYNG6phw4anfM53332nwsJCSdJ1112nyMjIc8oNAAAAAIC3UKj4kL/97W+mI0iSevXqpV69elX7+0yaNMn941tvvbXa3w8AAAAAAE/hUFo/VVxcrFdeeUUXXnihGjVqpLCwMDVs2FAXXXSR3n77bZWXlxvNV1hYqK+++kqS1KJFCw0cONBoHgAAAAAAqoIVKn5ozZo1GjFihHbt2uWY5+bmaubMmZo5c6Zef/11ffPNN8YOwp0yZYoOHz4sSbrllltkWZaRHAAAAAAAnA0KFT+zfft2DR48WAUFBapTp47Gjx+vXr16KTExUXv37tXXX3+t119/XcuWLdOIESM0b948hYaGej0n230AAAAAADUZhYqfGTNmjAoKCtStWzf9+OOPatCggePnhw0bpiuvvFJXXHGFlixZookTJ+ruu+/2asbU1FTNmzdPktS/f3+1bNnSq+8PAAAAAMC54gwVPzJv3jwtXLhQkvTee+8dV6b84tJLL3VfaTxx4kRvxXObPHmy+2rmMWPGeP39AQAAAAA4VxQqfuTrr7+WJLVt21adOnU65XMHDRokSVq2bJnXD6h9//33JUkREREaPXq0V98bAAAAAABPYMuPH1m+fLkkacuWLWd8yGtZWZny8/PVsGHD6ozmtnjxYm3dulWSNGLECMXExHjlfQEAAAAA8CRWqPiRnJycs3pdUVGRh5OcHIfRAgAAAAD8AStU/EhFRYUkqUuXLu5tNWeiadOm1RXJobS0VJ988okkKT4+XpdccolX3hcAAAAAAE+jUPEjsbGxkqSDBw+qY8eOhtMcb9q0acrPz5ck3XzzzQoODjacCAAAAACAs8OWHz/SrVs3SVJKSop2795tOM3x2O4DAAAAAPAXFCp+ZPjw4ZIk27b10ksvGU7jtHfvXn377beSjmxJ6tKli+FEAAAAAACcPQoVPzJs2DD16tVLkvTss8/q008/PeXz161bp2+++cYb0fTRRx+prKxMEqtTAAAAAAA1H2eo+JD58+dr+/bt7sd5eXnuH2/fvl0TJ050PP+222477nN8+OGH6tWrl/Lz83X99dfr/fff1/XXX6/WrVsrODhYOTk5WrVqlb755hstXrxYDz74oK666qrjPk/l91q9erX7x99//71SU1Pdj1u1aqUBAwac8n/bL9t9QkJCdPPNN5/yuQAAAAAA+DrLtm3bdAgccdttt+m999474+ef7Jdu69atGjVqlNavX3/az/G3v/1Njz766HFzy7LOOMeYMWOOK2COtXnzZrVv316SdPnll2v69Oln/LkBAAAAAPBFrFDxQ23atNHq1av16aef6vPPP9eyZcuUm5uriooKxcbGqm3bthowYIBGjhyp7t27V3ueyZMnu3/Mdh8AAAAAgD9ghQoAAAAAAEAVcSgtAAAAAABAFVGoAAAAAAAAVBGFCgAAAAAAQBVRqAAAAAAAAFQRhQoAAAAAAEAVcW2yIcXFxVq3bp0kKS4uTiEh/FIA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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 448, + "width": 554 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = withdrawall_base\n", + "df\n", + "\n", + "plt.axhline(0, c=\"black\", linewidth=0.4)\n", + "plt.plot(df['before_mix'], df['after_profit'])\n", + "# plt.ylim([-1e18,1e18])\n", + "plt.xlabel(\"Pool Mix\")\n", + "plt.ylabel(\"Withdraw All Profit\")\n", + "\n", + "display(df['after_profit'].min() / 1e18 ) \n", + "df\n", + "\n", + "\n", + "# for before_mix, rows in df.groupby(df['before_mix']):\n", + "# " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f882432-f9a5-467f-8489-9ebea6d32e25", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/brownie/balancer_test/amm_strat_report.ipynb b/brownie/balancer_test/amm_strat_report.ipynb new file mode 100644 index 0000000000..c695fd1661 --- /dev/null +++ b/brownie/balancer_test/amm_strat_report.ipynb @@ -0,0 +1,1374 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 74, + "id": "0693ee63-df90-468e-964b-e19a6ee3df8f", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'retina'\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "5b49a2fe-554f-427a-887b-b3880bf941f2", + "metadata": {}, + "outputs": [], + "source": [ + "def load_data(filename):\n", + " base = pd.read_csv(filename)\n", + " for x in base:\n", + " if \" \" in x or \"action\" in x:\n", + " continue\n", + " else:\n", + " base[x] = base[x].apply(int)\n", + " base['pre_mix'] = base['pre_pool_0'] / (base['pre_pool_0'] + base['pre_pool_1'])\n", + " base['before_mix'] = base['before_pool_0'] / (base['before_pool_0'] + base['before_pool_1'])\n", + " base['after_mix'] = base['after_pool_0'] / (base['after_pool_0'] + base['after_pool_1'])\n", + " base['before_profit'] = base['before_vault'] - base['pre_vault']\n", + " base['after_profit'] = base['after_vault'] - base['before_vault']\n", + " return base\n", + "\n", + "base = load_data(\"deposit_stats.csv\")\n", + "balance_base = load_data(\"balance_stats.csv\")\n", + "withdraw_base = load_data(\"withdraw_stats.csv\")\n", + "withdrawall_base = load_data(\"withdrawall_stats.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "id": "4273c012-881a-4a28-8f1a-6242f8c65195", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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4QUXyMvLkyRFR0dr5MiRbZ43YcIEx+v169d3aIyDBw+qtLT0guu0N05JSYkKCws7NA7gifl8qerr6x2vg4OD3TIG/J8Vc/q+++5TTU2N7rzzTk2cOPGyrgW05In53NDQ4Phlz5QpUxQRESFJam5uVlFRkQoLC1VXV9fR1IELeOr787lfSh48eLDNcyorK3X8+HHT+YA3KigocBQH27svDAsLc/yyvqCgQI2NjR7Jz1UovOACu3btkiT169dPISEhbZ43cODACz5zqb788stWr+PqcQBPzOdL9dFHHzleDxo0yC1jwP95ek7n5ubq7bffVteuXfVf//Vfnb4O0BpPzOft27c7CitDhw5VZWWlHnroISUmJio9PV29e/dWXFycpkyZonXr1nX8iwD+j6e+P99zzz2SpIqKCj3//POtnvPb3/72gvMBb9SZ+8Kmpibt3bvXrXm5GoUXmNTV1Tmq420t8zqna9euio6OliQVFRV1aJzi4mLH64uNk5aW5njd0XEQ2Dw1ny/F9u3btWrVKklnf/Cn8ILO8PScPnnypB566CFJ0hNPPKGkpKROXQdojafmc8sf6u12u7KysvTHP/5Rp06dcsQbGhr0wQcf6LrrrtOTTz7ZoesDkme/Py9cuNDxuNL999+v733ve1qxYoU2b96sZcuWaebMmXrmmWckSb/4xS80efLkDo8BeEqg3BdSeIFJVVWV43VMTMxFzz/3j0Z1dbXbxjk3RmfGQWDz1Hy+mPr6en33u99Vc3OzJOnxxx936fURODw9px9++GEdPXpUY8eO1fe+971OXQNoi6fm84kTJxyvn3zySe3du1fTpk1Tfn6+6urqdOzYMT333HOKi4uTYRh65JFHHI8mAZfKk9+fg4OD9fe//12vvfaarrrqKr3wwgu6+eablZ2drdmzZ2v58uWaNGmSVq9erd/97ncdvj7gSYFyX0jhBSYtn3G+lOaJ4eHhkqQzZ864bZxzY3RmHAQ2T83ni3nggQe0efNmSdK8efM0ffp0l14fgcOTc/rjjz/WokWLFBISoueff142m63D1wDa46n5XFNTYxpzypQpWrlypbKzsxUeHq6kpCTdc889WrlypYKCzv5o/LOf/YyG/ugQT//MsWvXLr300kv64osvWn1/48aNevHFF1VSUtKp6wOeEij3hRReYHKu4Zx0aR3QzzULjYyM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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 428, + "width": 559 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = base\n", + "plt.axhline(0, c=\"grey\", linewidth=0.5)\n", + "plt.axhline(0, c=\"black\", linewidth=0.4)\n", + "for before_mix, rows in df.groupby(df['before_mix']):\n", + " plt.plot(rows['action_mix'], rows['after_profit'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "34c14a7e-adf1-445c-97fc-8bec0a003dcc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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/vmnLl68qNTUVF2+fFkbN27Uk08+qQ4dOujixYs2q6FBgwam43/++SfXfidPnjR7DgAgb1euXNHChQtNj3v16pXjLmItWrQw7Sd06dIlhYeHW72OHTt25NsnPT092ybhrVq1ytbesmVL0/GuXbsKtETtr7/+ynZ+YWYcZQZxa9as0X333Wd6fu3atQUeIyt7znayxvttCXt/j25HcZ99BgAoHQiXUKqFh4era9euOnPmjDw9PfXKK69o9erV2rNnj9avX6/x48fLyclJu3fv1oABA5SammqTOu666y516NBBkrRgwYJsm8pmio2N1aeffirp5uymnj172qQWAChtjEajRowYkW0fnFdffTVHv7Jly+qee+4xPf7iiy+sXsvatWsVExOTZ5/ffvtNly5dkiS5urrmuONZhw4dTCHY5cuXFRQUlOd4GRkZmj9/vulx1tdYGAaDQf369TM9tvSPLq6urqZjW/1czWSN99sSRfU9soQ9vx8AgDsX4RJKtREjRujGjRtq2bKlTp48qXfffVcDBw5UYGCgevbsqVmzZmndunVycHDQzp07tWDBApvVMn/+fNWuXVtXr15Vq1at9PHHH2vTpk3aunWrvvrqKzVv3lynTp1ShQoVtGTJErm4uNisFgAoLeLi4vTII49k+3D/r3/9K9cA4eWXXzYdf/755/rjjz8KfK2CLKWLiYnRlClTcm2Pj4/X5MmTTY8HDx6cY4aVt7e3hg4danr80ksv5bn586xZs0x3MHVwcNBTTz2VrT02NrbAS62zLh+rVKlSgc65la+vr+n43LlzFo1RUNZ4vy1h7e+RLdnz+wEAuHMRLqHUCgkJMU1BX7hwYa57LPTq1UuDBw+WJJuGS/Xr19fu3bs1bdo0xcfHm+4W17lzZz399NOKjIzUiy++qP379+fYhBYAkF1UVJQ++ugjNW7cWCtXrjQ936FDB33zzTe5nte1a1eNGDFC0s07v/Xp00fvvfdetllPWSUlJWnNmjUaMGBAtj2JcuPi4qLZs2frP//5T45A59y5c+rTp49CQ0Ml3ZxJ9cYbb5gd5/XXXzdtGn38+HHdf//9OZZVZ2RkaObMmXrhhRdMz40fPz7bLe8lae/evapVq5amTp1quvat0tPTtWLFCn3++eem5x544IF8X685tWvXNt3F7cyZM9mWpFmbtd5vS1jze2RLTZs2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H37YovqLM8IlAAAAAABgFePHj1dcXJxGjBihrl27FuiclJQUSVLt2rVz7ePl5aUKFSpk619Ya9euNc2QGjVqVK79Ro4cKenm8r61a9dma7tx44YkqWrVqjnOq1KlSrY+mS5cuKCpU6fK2dlZs2bNsqj24o5wCQAAAAAA3LaVK1fq559/lo+Pjz766KMCn9egQQNJ0qlTp3LtExMTo+jo6Gz9C2vr1q2m47yCr6xt27Zty9bm5eUlSTlmNGV9LrNPpkmTJik2NlbPP/98qdrEOyvCJQAAAAAAcFuuX79uukva9OnTTbOMCuLf//63JOnKlSv66quvzPaZNm1ajv6FFRoaKulm+JM5y8icqlWrytPTU5IUFhaWra158+aSpKCgICUkJJiez8jI0Pfffy9JatGihen5TZs2admyZapevbppuWBp5FTUBQAAAAAAYE8ZGUZdS7BsaVVJVL6cixwcDDa9xuTJkxUVFaWOHTsWaBPvrJ544glt3bpVixYt0vjx47V37171799fVatW1dmzZ7V48WKtWbNG0s0Nue+9916Lasy8+5ufn1++ff39/XXkyBFFRERke37AgAHy9PTU5cuX1atXL73yyitycXHR559/rtDQUDk5Oemxxx6TdHMT7wkTJkiSPv7442x7NJU2hEsAAAAAgDvKtYQUBb79R1GXYTd7X71Xvu5lbDZ+SEiI5s6dKycnJ3311VcyGAoXZDk6OmrhwoXq16+f3n33Xc2dO1dz587N1qd79+6aMmWKxcGSJMXGxkpSgUKezLu5xcXFZXvey8tLs2fP1vDhwxUSEqKQkJBs7dOnT1edOnUkSZ9++qmOHDlSajfxzoplcQAAAAAAwCIpKSl66qmnZDQa9fzzz6tp06YWjRMWFqZFixbp0KFDZtu3b9+uefPm6dy5cxbXmpSUJEkFuoNdmTI3w7jExMQcbcOGDdP69evVtWtXubu7q1y5crr77ru1atUqvfDCC5Kkc+fO6c0335Szs7M+//xz07m///67unXrJg8PD7m7u6tbt27auHGjxa+puCBcAgAAAAAAFnn33Xd19OhR1ahRQ2+88YZFY4SEhKh9+/Zat26dqlevrsWLFysqKkopKSmKiIjQ7NmzVa5cOS1fvlxt27bVkSNHLLqOq6urpILdbS45OVmSVLZsWbPt9913nzZt2qTY2FjFx8dr+/bt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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 454, + "width": 587 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = base\n", + "plt.title(\"Deposit profit\")\n", + "plt.axhline(0, c=\"grey\", linewidth=0.5)\n", + "plt.axhline(0, c=\"black\", linewidth=0.4)\n", + "for before_mix, rows in df.groupby(df['before_mix']):\n", + " plt.plot(rows['action_mix']*100, rows['after_profit'], label=\"{:.1f}%\".format(100*float(before_mix)))\n", + "plt.ylim([-1e18,1e18])\n", + "plt.xlabel(\"Deposit Mix\")\n", + "plt.ylabel(\"Deposit Profit\")\n", + "plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "c6e801c3-e642-4a72-b0c7-6e97277ff5dd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABFkAAANYCAYAAAAfZjIVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/OQEPoAAAACXBIWXMAAB7CAAAewgFu0HU+AABR6ElEQVR4nO3deZyXZaH///fACIMIoSK4MBK5oYaaOmSZmhuliUtZcUoTO2aWVnbcfnUS8ZSeg9ly8uv6RcFMxd0UTc0kEw4qpnUw7CQqAicQcAlEtoHP7w/i84Vg2LxGmOH5fDx4PG7mvj/XfY1dofPiXmoqlUolAAAAALwrbTb0BAAAAABaA5EFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRZSM3Y8aMjBw5MoMGDcpRRx2Vrl27pqamJjU1NRk4cOB7No8lS5ZkwoQJGT58eL7+9a+noaEh7du3r87lt7/97TqPOXfu3Fx55ZU5/PDDs8MOO6R9+/bp3r179t1333zjG9/II488Uv4bAQAAgGZSu6EnwOp17959Q08hSXLTTTcVjTqjRo3KqaeemldffXWFr8+YMSMzZszIc889lyeeeCL9+vUrdk4AAABoTiJLC7Ljjjumd+/eG+QKj0qlUt3ebLPN0qdPnyxatCjjx49f57EeffTR9O/fP/Pnz0+XLl1yxhln5OMf/3i6deuWd955Jy+88EJGjhyZ1157reS3AAAAAM1KZNnIDRo0KA0NDWloaEj37t0zadKk9OrV6z2fxx577JGf/exnaWhoyD777JO6uroMHjx4nSPLzJkzM2DAgMyfPz/77LNPHnrooZWu1jnwwANz2mmnZeHChSW/BQAAAGhWIstG7uKLL97QU0iS9O3bN3379n3X43znO9/J66+/ns033zz33nvvam+Hateu3bs+HwAAALxXPPh2EzJ//vz8n//zf3L44Ydn2223Tbt27dKtW7ccccQRuf7669PY2Nis53/zzTdzyy23JElOOumk9OzZs1nPBwAAAO8lV7JsIv74xz/muOOOW+lBszNnzsxvfvOb/OY3v8m1116b+++/v9ketjty5MjMmzcvSXLsscdWv/7OO+/kr3/9a7bYYot07949NTU1zXJ+AAAAaE6uZNkETJw4MYccckheffXVdO7cOd/5zndyzz335JlnnsnDDz+cM888M7W1tRk3blyOO+64LFq0qFnm8eSTT1a3+/Tpk3HjxqVfv37p1KlTdtlll2y33Xbp3r17zjrrLA+9BQAAoMVxJcsm4JRTTsnf/va3fOhDH8ojjzySrl27rrC/X79+OeaYY/KpT30qTz31VIYPH56vfOUrxecxYcKE6vaoUaNy2mmnrXSL0syZM3PllVfmrrvuykMPPZS99967+DwAAACgObiSpZV74okn8l//9V9JkhtvvHGlwLLMJz/5yZx44olJkuHDhzfLXN54443q9hlnnJGampr84Ac/yOTJk7NgwYL86U9/ysCBA5Mk06dPz/HHH5/Zs2c3y1wAAACgNJGllbvvvvuSJLvttlv69Omz2mMPPvjgJMm4ceOa5SG4c+fOrW7Pnz8/119/ff71X/819fX1adeuXfbYY48MGzYsp59+epJk0qRJufrqq4vPAwAAAJqDyNLKPfPMM0mS//mf/0lNTc1qf5111llJkkWLFq1w1UkpdXV11e299torJ5988iqPu/TSS9O+ffskyW233VZ8HgAAANAcRJZWbsaMGev1uXfeeafwTJJOnTpVt/v169fkcVtvvXX233//JEvfirRw4cLicwEAAIDSPPi2lVu8eHGSZO+9984vfvGLtf7cDjvsUHwu9fX11TcM1dfXr/HYJFmyZEneeOONbLvttsXnAwAAACWJLK3c1ltvnSR5++2388EPfnCDzmXPPffMHXfckeT/xZ+mLL+/ttYyBQAAYOPndqFW7kMf+lCS5OWXX8706dM36FyWPVg3WTqf1XnppZeSLH2Oy1ZbbdWs8wIAAIASRJZW7thjj02SVCqV/Od//ucGncvBBx+cbbbZJkly//33N3k1yyuvvJI//OEPSZIDDzwwbdpYpgAAAGz8/PTayvXr1y99+/ZNkvzwhz/M7bffvtrjx48fn/vvv79Z5tK2bduce+65SZJXX3013//+91c6prGxMV//+tezZMmSJMkZZ5zRLHMBAACA0moqlUplQ0+Cpo0ePToTJ06s/n7WrFk577zzkiy9yuO0005b4fiBAweuNMZLL72Uvn37Vl/L3L9//3z+85/PLrvskrZt22bGjBl57rnncv/99+fJJ5/MOeeck8svv3ylcYYPH77C7++999788pe/TJJccMEF6d27d3XfzjvvnI997GMrjTF//vwceOCBefbZZ5MkAwYMyCmnnJJu3brlpZdeyk9+8pOMHTs2SXL00Udn5MiRqampWdM/JgAAANjgRJaN3MCBA3PjjTeu9fFN/c/5l7/8JZ/5zGfy/PPPr3GMiy++OIMGDVrp6+sSO0455ZSVoswy06ZNS//+/fP73/++yc8fffTRGTFixAqvfQYAAICNmde2bCJ23XXX/OEPf8jtt9+eu+66K+PGjcvMmTOzePHibL311tltt93ysY99LCeccEL23XffZp3LdtttlyeffDLXX399br311kyYMCFvvfVWtt566/Tt2zcDBw7MCSec0KxzAAAAgNJcyQIAAABQgAffAgAAABQgsgAAAAAUILIAAAAAFCCyAAAAABTg7UIbkfnz52f8+PFJkm222Sa1tf7nAQAAgNIaGxszc+bMJEmfPn1SV1dXZFw/xW9Exo8fn759+27oaQAAAMAm4+mnn05DQ0ORsdwuBAAAAFCAK1k2Ittss011++mnn8522223AWcDAAAArdO0adOqd5Is/7P4uyWybESWfwbLdtttlx49emzA2QAAAEDrV/J5qG4XAgAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKKBZI8uMGTMycuTIDBo0KEcddVS6du2ampqa1NTUZODAgcXO09jYmOeeey7XXnttTjvttOy1116pra2tnmvSpElrNc6ECRPywx/+MMccc0ze//73p66uLptvvnl69eqVAQMG5MEHHyw2ZwAAAKB1qW3Owbt3796cw1ddcsklGTx48Lsa45RTTsnPf/7zVe6bNGlSJk2alNtuuy2f+MQnMmLEiHTp0uVdnQ8AAABoXd6z24V23HHH9OvXr1nGrlQq1e26uroccMAB2WmnndZpjP/93/9Nkmy11VY5/fTTc8stt+S//uu/8vTTT+faa6/NbrvtliR5+OGH079//yxZsqTcNwAAAAC0eM16JcugQYPS0NCQhoaGdO/ePZMmTUqvXr2Kn+cjH/lIrrnmmvTt2zd9+vRJbW1tBg4cmJdeemmtx6ivr8+1116bU045Je3bt19hX0NDQ0466aR84hOfyOjRozN69Oj84he/yJe+9KXS3woAAADQQjVrZLn44oubc/iqT3ziE+96jGHDhq12/+abb56rr746ffr0SZLceeedIgsAAABQ5e1C6+CDH/xgunbtmiTrdJUMAAAA0PqJLOto4cKFSZK2bdtu4JkAAAAAG5NmvV2otXnuuecye/bsJMnuu+++zp+fOnXqavdPmzZtveYFAAAAbHgiyzq49NJLq9uf+9zn1vnz9fX1JacDAAAAbETcLrSW7rrrrtx5551Jkv322y+f/vSnN/CMAAAAgI2JK1nWwgsvvJBTTz01SdKhQ4fcdNNNqampWedxpkyZstr906ZNS9++fddrjgAAAMCGJbKswV//+tccffTRmTNnTmpqanLDDTes1/NYkqRHjx6FZwcAAABsLNwutBpvvPFG+vXrl0mTJiVJrrjiigwYMGDDTgoAAADYKIksTZgzZ04++clP5k9/+lOS5Pvf/37OPPPMDTwrAAAAYGMlsqzCvHnz0r9//4wbNy5Jct555+V73/veBp4VAAAAsDETWf7BokWL8pnPfCaPP/54kuSMM87IZZddtoFnBQAAAGzsRJblLF68OF/4whfyq1/9Kkly8skn56qrrtrAswIAAABago0+sgwfPjw1NTWpqanJ4MGDm+08lUolX/nKV3LnnXcmST7zmc9k2LBh6/WqZgAAAGDT06yvcB49enQmTpxY/f2sWbOq2xMnTszw4cNXOH7gwIHrdZ633367GkeWH3+ZO++8M127dq3+fp999sk+++yzwvHnnntuhg0bliT54Ac/mO9+97t54YUXVnveD37wg+s1XwAAAKD1adbIMnTo0Nx4442r3DdmzJiMGTNmha+tb2SZNWtWTj311Cb3n3feeSv8/qKLLlopstx1113V7eeffz777bffGs9bqVTWbaIAAABAq7XR3y4EAAAA0BLUVFyOsdGYOnVq6uvrkyRTpkxJjx49NvCMAAAAoPVprp+/XckCAAAAUIDIAgAAAFCAyAIAAABQgMgCAAAAUIDIAgAAAFCAyAIAAABQgMgCAAAAUIDIAgAAAFCAyAIAAABQgMgCAAAAUIDI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5bbbbsuSJUuaZe4AAABAy1XbnIN37969OYdfwbx583LiiSfmwQcfXOHrkydPzs0335xbb701gwYNykUXXdTkGAsWLMgXv/jF3HXXXSvtmzp1aqZOnZr77rsvV155Ze6777506dKl9LcBAAAAtFDv2e1CO+64Y/r169ds43/5y1+uBpZDDz009957b55++ulcf/312WmnnbJkyZIMHjw41113XZNjfPOb36wGlm7duuXyyy/PY489lieeeCJXXXVVevbsmSR54oknMmDAgGb7XgAAAICWp6ZSqVSaa/CLLrooDQ0NaWhoSPfu3TNp0qT06tUrSXLKKadk+PDhRc7z2GOP5fDDD0+S9O/fP/fcc0/atm1b3T9r1qzst99+mTx5crp06ZKXX345W2655QpjvPbaa9l+++2zZMmSbLnllvnv//7v9OjRY4VjZs+enb333juTJk1KkowbNy77779/ke8hWXq1TH19fZJkypQpK50fAAAAePea6+fvZr2S5eKLL84xxxzT7LcNXX755UmS2traXHXVVSsEliTp2rVrhgwZkiR56623MnTo0JXGeOqpp6rPWjn11FNX+Q+4c+fO+fa3v139/bo85wUAAABo3Vr824XmzJmT3/zmN0mSI444osn69OlPfzqdO3dOktxzzz0r7V+4cGF1+wMf+ECT59tpp51W+RkAAABg09biI8u4ceOqseOQQw5p8rh27drlgAMOqH5m0aJFK+zfbbfdqtsvv/xyk+O89NJLq/wMAAAAsGlr8ZFlwoQJ1e3evXuv9thl+xsbG/Piiy+usK9Pnz756Ec/miQZPnx4/vrXv670+Tlz5uSnP/1pkqVXu6zrg3yXvaGoqV/Tpk1bp/EAAACAjUezvsL5vTB16tTq9poeVLPsoTbJ0gfb7LHHHivsHzZsWD75yU/mlVdeyb777pvzzz8/++67b2pra/P888/nsssuyyuvvJKuXbvm5ptvTrt27dZprsufHwAAAGhdWnxkmTNnTnV7iy22WO2xHTt2rG6//fbbK+3fddddM27cuFx99dUZMmRIzjnnnBX2b7bZZjn33HPzrW99y5t/AAAAgBW0+Mgyf/786vaarixp3759dXvevHmrPOb+++/PzTffvMoIs2jRotx+++3ZZpttct5556Wmpmad5jplypTV7p82bVr69u27TmMCAAAAG4cWH1nq6uqq22t628+CBQuq2x06dFhp/znnnJMf//jHSZLjjz8+5513Xvbee++0bds2L7zwQq644ooMGzYsF1xwQZ566qncfvvtK70uenVc/QIAAACtV4t/8G2nTp2q26u6+mR5c+fOrW7/461FDzzwQDWwDBw4MPfcc08++tGPpmPHjqmrq8uHPvSh3HDDDbnwwguTJHfffXeuuuqqUt8GAAAA0MK1+Miy/NUhyz8Ed1WWv13nHx9CO3To0CRJTU1NfvCDHzQ5xne/+91qoLnhhhvWeb4AAABA69TiI8vybwj685//vNpjl+2vra3NLrvsssK+F154IUnSrVu37LDDDk2OUVdXlz333HOtzgcAAABsOlp8ZGloaKg+8Pbxxx9v8riFCxfmySefrH5ms802W2F/be3Sx9M0Njau8ZyLFi1a4TMAAAAALT6ydOrUKYcffniS5NFHH23ylqG77747s2fPTpKccMIJK+3v1atXkuT111+vXtWyKm+88Uaef/75FT4DAAAAsNFHluHDh6empiY1NTUZPHjwKo8599xzkyy9CuXMM8/M4sWLV9g/a9asXHDBBUmSLl265LTTTltpjP79+1e3zz777FW+qWjJkiX55je/Wd13zDHHrNf3BAAAALQ+zXq/y+jRozNx4sTq72fNmlXdnjhxYoYPH77C8QMHDlyv8xx22GEZMGBARowYkfvuuy9HHnlkzj777Gy//fYZP358LrnkkkyePDlJMmTIkGy55ZYrjTFw4MD89Kc/zQsvvJBHHnkk+++/f77xjW9UX+E8YcKEXH311Rk7dmySpHv37vmXf/mX9ZovAAAA0Po0a2QZOnRobrzxxlXuGzNmTMaMGbPC19Y3siRL3/Qze/bsPPjggxk1alRGjRq1wv42bdrkwgsvzOmnn77Kz7dr1y6/+tWvctxxx+WPf/xjxo8f3+SxvXr1yt13352uXbuu93wBAACA1qXVPLm1Q4cOeeCBB3LLLbdk+PDh+eMf/5i33nor3bt3z0EHHZSzzjorH/nIR1Y7Rs+ePTNu3LiMGDEid955Z5599tnMnDkzlUolW221Vfbaa68cf/zx+dKXvpSOHTu+R98ZAAAA0BLUVCqVyoaeBEtNnTo19fX1SZIpU6akR48eG3hGAAAA0Po018/fG/2DbwEAAABaApEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoIBmjSwzZszIyJEjM2jQoBx11FHp2rVrampqUlNTk4EDBzbLOW+99db069cv2267berq6tKzZ8+cdNJJGTt27DqNM3fu3Fx55ZU5/PDDs8MOO6R9+/bp3r179t1333zjG9/II4880izzBwAAAFqm2uYcvHv37s05/ArmzZuXE088MQ8++OAKX588eXJuvvnm3HrrrRk0aFAuuuiiNY41atSonHrqqXn11VdX+PqMGTMyY8aMPPfcc3niiSfSr1+/ot8DAAAA0HI1a2RZ3o477pjevXs32xUgX/7yl6uB5dBDD823vvWtbL/99hk/fnwuvfTSvPTSSxk8eHC22267nH766U2O8+ijj6Z///6ZP39+unTpkjPOOCMf//jH061bt7zzzjt54YUXMnLkyLz22mvN8n0AAAAALVNNpVKpNNfgF110URoaGtLQ0JDu3btn0qRJ6dWrV5LklFNOyfDhw4uc57HHHsvhhx+eJOnfv3/uueeetG3btrp/1qxZ2W+//TJ58uR06dIlL7/8crbccsuVxpk5c2Z23333vP7669lnn33y0EMPNXk1zsKFC9OuXbsi819m6tSpqa+vT5JMmTIlPXr0KDo+AAAA0Hw/fzfrM1kuvvjiHHPMMc1+29Dll1+eJKmtrc1VV121QmBJkq5du2bIkCFJkrfeeitDhw5d5Tjf+c538vrrr2fzzTfPvffeu9p5lw4sAAAAQMvW4t8uNGfOnPzmN79JkhxxxBFN1qdPf/rT6dy5c5LknnvuWWn/m2++mVtuuSVJctJJJ6Vnz57NNGMAAACgNWrxkWXcuHFZuHBhkuSQQw5p8rh27drlgAMOqH5m0aJFK+wfOXJk5s2blyQ59thjq19/5513MnHixEyfPj3NeGcVAAAA0MK1+MgyYcKE6nbv3r1Xe+yy/Y2NjXnxxRdX2Pfkk09Wt/v06ZNx48alX79+6dSpU3bZZZdst9126d69e84666z1fujt1KlTV/tr2rRp6zUuAAAAsOG9Z28Xai5Tp06tbq/pQTXLHmqTLH2wzR577FH9/fKxZtSoUTnttNPS2Ni4wudnzpyZK6+8MnfddVceeuih7L333us01+XPDwAAALQuLf5Kljlz5lS3t9hii9Ue27Fjx+r222+/vcK+N954o7p9xhlnpKamJj/4wQ8yefLkLFiwIH/6058ycODAJMn06dNz/PHHZ/bs2QW+AwAAAKA1aPFXssyfP7+6vaY3/rRv3766vez5K8vMnTt3hTF//vOf5+STT65+bY899siwYcPSrl27XHfddZk0aVKuvvrqXHDBBWs91ylTpqx2/7Rp09K3b9+1Hg8AAADYeLT4yFJXV1fdXvYA3KYsWLCgut2hQ4cmx9lrr71WCCzLu/TSS3PjjTdmwYIFue2229YpspR67zYAAACw8Wnxtwt16tSpuv2PtwD9o+WvVvnHW4uWH6dfv35NjrH11ltn//33T5L88Y9/XGPYAQAAADYNLT6yLH91yPIPwV2V5W/X+ceH0C7/+zU9oHbZ/iVLlqzwLBcAAABg09XiI8vybwj685//vNpjl+2vra3NLrvsssK+Pffcs7q9ePHi1Y6z/P7a2hZ/xxUAAABQQIuPLA0NDdUH3j7++ONNHrdw4cI8+eST1c9sttlmK+w/+OCDq9svv/zyas/50ksvJVn6HJetttpqveYNAAAAtC4tPrJ06tQphx9+eJLk0UcfbfKWobvvvrv6yuUTTjhhpf0HH3xwttlmmyTJ/fff3+TVLK+88kr+8Ic/JEkOPPDAtGnT4v8RAgAAAAVs9IVg+PDhqampSU1NTQYPHrzKY84999wkSWNjY84888yVAsmsWbOqbwHq0qVLTjvttJXGaNu2bXWcV199Nd///vdXOqaxsTFf//rXs2TJkiTJGWecsd7fFwAAANC6NOsDRUaPHp2JEydWfz9r1qzq9sSJEzN8+PAVjh84cOB6neewww7LgAEDMmLEiNx333058sgjc/bZZ2f77bfP+PHjc8kll2Ty5MlJkiFDhmTLLbdc5Tjf/OY3c9ttt+XZZ5/NxRdfnP/5n//JKaeckm7duuWll17KT37yk4wdOzZJcvTRR+czn/nMes0XAAAAaH2aNbIMHTo0N9544yr3jRkzJmPGjFnha+sbWZLkhhtuyOzZs/Pggw9m1KhRGTVq1Ar727RpkwsvvDCnn356k2PU1dVl5MiR6d+/f37/+99nxIgRGTFixErHHX300RkxYkRqamrWe74AAABA67LR3y60tjp06JAHHnggN998c4488sh069Yt7dq1S319fb7whS9k9OjRTd5utLztttsuTz75ZK655poccsgh2WabbbLZZptl2223zbHHHpu77747DzzwQDp16tT83xQAAADQYtRUKpXKhp4ES02dOjX19fVJkilTpqRHjx4beEYAAADQ+jTXz9+t5koWAAAAgA1JZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAoQGQBAAAAKEBkAQAAAChAZAEAAAAooFkjy4wZMzJy5MgMGjQoRx11VLp27ZqamprU1NRk4MCBzXLOW2+9Nf369cu2226burq69OzZMyeddFLGjh273mP+6le/qs67pqYmgwcPLjdhAAAAoFWobc7Bu3fv3pzDr2DevHk58cQT8+CDD67w9cmTJ+fmm2/OrbfemkGDBuWiiy5ap3Hnzp2br33tayWnCgAAALRC79ntQjvuuGP69evXbON/+ctfrgaWQw89NPfee2+efvrpXH/99dlpp52yZMmSDB48ONddd906jXvhhRfm1VdfTbdu3Zpj2gAAAEAr0ayRZdCgQbn//vszffr0vPrqq7n22mub5TyPPfZYRowYkSTp379/fv3rX+e4445LQ0NDvvzlL+fJJ5/MjjvumCS54IIL8uabb67VuL///e/zs5/9LO3bt88ll1zSLHMHAAAAWodmjSwXX3xxjjnmmGa/bejyyy9PktTW1uaqq65K27ZtV9jftWvXDBkyJEny1ltvZejQoWscc/HixfnKV76SxYsX57vf/W523nnn8hMHAAAAWo0W/3ahOXPm5De/+U2S5IgjjkiPHj1WedynP/3pdO7cOUlyzz33rHHcn/zkJ3nuueey66675oILLig3YQAAAKBVavGRZdy4cVm4cGGS5JBDDmnyuHbt2uWAAw6ofmbRokVNHjtp0qTqA3KvvvrqtG/fvuCMAQAAgNaoWd8u9F6YMGFCdbt3796rPbZ379555JFH0tjYmBdffDF77LHHKo/72te+lnfeeSdf/OIXc9hhhxWb69SpU1e7f9q0acXOBQAAALy3WnxkWT5cNHWr0DL19fXV7SlTpqwystxyyy156KGH0qVLl/z4xz8uN9F/OD8AAADQurT424XmzJlT3d5iiy1We2zHjh2r22+//fZK+9944418+9vfTpL8+7//u9c2AwAAAGutxV/JMn/+/Op2u3btVnvs8s9WmTdv3kr7zz333MyYMSMf/vCHc/rpp5eb5N9NmTJltfunTZuWvn37Fj8vAAAA0PxafGSpq6urbi97AG5TFixYUN3u0KHDCvt++9vfZtiwYWnbtm2uueaatGlT/iKfNd3OBAAAALRcLf52oU6dOlW3V3UL0PLmzp1b3V7+1qIFCxbkq1/9apLkm9/8ZvbZZ5+ykwQAAABavRZ/JcvyV4dMnTo1+++/f5PHLn+7zvIPob377rvzl7/8JZtttln22GOPjBgxYqXPLv8Wo+eff756zIc//OH06tXrXX0PAAAAQMvX4iPL8m8I+vOf/7zaY5ftr62tzS677FL9+rLbiBYtWpSvfOUrazznXXfdlbvuuitJMmzYMJEFAAAAaPm3CzU0NFQfePv44483edzChQvz5JNPVj+z2WabvSfzAwAAADYNLT6ydOrUKYcffniS5NFHH83UqVNXedzdd9+d2bNnJ0lOOOGEFfYNHDgwlUpltb9GjRpVPf6iiy6qfn3gwIHN840BAAAALcpGH1mGDx+empqa1NTUZPDgwas85txzz02SNDY25swzz8zixYtX2D9r1qxccMEFSZIuXbrktNNOa9Y5AwAAAJueZn0my+jRozNx4sTq72fNmlXdnjhxYoYPH77C8et7Vchhhx2WAQMGZMSIEbnvvvty5JFH5uyzz87222+f8ePH55JLLsnkyZOTJEOGDMmWW265XucBAAAAaEqzRpahQ4fmxhtvXOW+MWPGZMyYMSt87d3cenPDDTdk9uzZefDBBzNq1KgVbu9JkjZt2uTCCy/M6aefvt7nAAAAAGjKRn+70Nrq0KFDHnjggdx888058sgj061bt7Rr1y719fX5whe+kNGjRzd5uxEAAADAu1VTqVQqG3oSLDV16tTU19cnSaZMmZIePXps4BkBAABA69NcP3+3mitZAAAAADYkkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACggGaNLDNmzMjIkSMzaNCgHHXUUenatWtqampSU1OTgQMHNss5b7311vTr1y/bbrtt6urq0rNnz5x00kkZO3bsGj87adKkXHHFFfnMZz6TXXbZJZtvvnnq6urSo0ePHH/88RkxYkQaGxubZd4AAABAy1ZTqVQqzTZ4TU2T+0455ZQMHz682LnmzZuXE088MQ8++OAq97dp0yaDBg3KRRddtMr9F154YS655JKs6R9HQ0ND7rzzzuy4447ves7/aOrUqamvr0+STJkyJT169Ch+DgAAANjUNdfP3+/Z7UI77rhj+vXr12zjf/nLX64GlkMPPTT33ntvnn766Vx//fXZaaedsmTJkgwePDjXXXfdKj8/bdq0VCqVdOzYMSeddFKGDRuW0aNH55lnnslNN92UhoaGJMm4ceNyxBFH5O2332627wUAAABoeZr1SpaLLrooDQ0NaWhoSPfu3TNp0qT06tUrSdkrWR577LEcfvjhSZL+/fvnnnvuSdu2bav7Z82alf322y+TJ09Oly5d8vLLL2fLLbdcYYwLLrggW2+9db72ta+lU6dOK51j8eLF+cIXvpDbb789SXLxxRdn0KBBRea/jCtZAAAAoPm1yCtZLr744hxzzDHp3r17c54ml19+eZKktrY2V1111QqBJUm6du2aIUOGJEneeuutDB06dKUxhgwZkvPPP3+VgSVJ2rZtm6uuuirt2rVLktx5550lvwUAAACghWvxbxeaM2dOfvOb3yRJjjjiiCbr06c//el07tw5SXLPPfes17m23nrr7LXXXkmSl156ab3GAAAAAFqnFh9Zxo0bl4ULFyZJDjnkkCaPa9euXQ444IDqZxYtWrRe51uwYEGSrHS1DAAAALBpq93QE3i3JkyYUN3u3bv3ao/t3bt3HnnkkTQ2NubFF1/MHnvssU7nmjFjRl544YUkye67777Oc506depq90+bNm2dxwQAAAA2Di0+siwfLtb0oJplD7VJlj7YZl0jyw9/+MM0NjYmST73uc+t02f/8fwAAABA69LibxeaM2dOdXuLLbZY7bEdO3asbq/rK5ifeuqp/PSnP02yNOZ87WtfW6fPAwAAAK1bi7+SZf78+dXtZW/+aUr79u2r2/PmzVvrc7z22ms58cQT09jYmJqamtx4443ZfPPN13muU6ZMWe3+adOmpW/fvus8LgAA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qU99qjrXv/zlL00e98UvfrGSpLLZZptVXn/99Xc9V1qP92q9l4gsCxcurLzvfe+rJKnsvvvulcWLF6/yuK9+9avVcz399NPrdS42Dh58yybv3nvvrW4vuxzwH7Vp0yZf+tKXkiRvvfVWRo0a9a7O+eqrr2bQoEFJkmuuuSbt2rVbq8+9+eabueWWW5IkJ510Unr27Pmu5sGmpyWt9zWZPXt2fvnLXyZJevXqlYMOOqjIuLQeLWm9L1y4sLr9gQ98oMnjdtppp1V+BlrSen/mmWeSJDvvvHN22WWXJo/75Cc/mSRZtGhR7rvvvnc1V1qXDbHe19eoUaPyt7/9LUlyyimnpE2bVf8IPnDgwOr2Pffc815MjWYisrDJGz16dJKkY8eO2W+//Zo87pBDDqlujxkz5l2d8+tf/3rmzp2bk08+OR//+MfX+nMjR47MvHnzkiTHHnts9evvvPNOJk6cmOnTp6fiMUusRkta72tyxx13VP//cPLJJ6empqbY2LQOLWm977bbbtXtl19+ucnjXnrppVV+BlrSen/99deTJN27d1/tccvv/93vfrdec6R12hDrfX0tm2uy4nz+0f7775/NN988yYabK2WILGzyXnjhhSRL/zaltra2yeN69+690mfWx4gRI/Lggw9myy23zI9+9KN1+uyTTz5Z3e7Tp0/GjRuXfv36pVOnTtlll12y3XbbpXv37jnrrLPy2muvrfccab1a0npfk5///OfV7WV/UwXLa0nrvU+fPvnoRz+aZOmDFv/617+udMycOXPy05/+NMnSq1369eu33nOl9WlJ632LLbZIkurf7jdl+f0TJkxY90nSar3X6z1ZesXM9ttvn3bt2lVfNf69730v//u//7vazy2/dpefzz+qra3NzjvvXGSubFgiC5u0+fPnZ9asWUmWPhF8dbbccst07NgxSTJlypT1Ot+bb76Zs88+O0nyH//xH9lmm23W6fPL/yE9atSofPSjH82vf/3rLFmypPr1mTNn5sorr8w+++yTP/7xj+s1T1qnlrbeV2fSpEl54oknkiQHHnjgCrdQQNIy1/uwYcPSq1evvPHGG9l3333z4x//OL/97W8zevToXHPNNdl7773zyiuvpGvXrrn55puL3XpHy9fS1vvuu++eZOkPkjNnzmzyuOWvXpk8efK6T5RW6b1e78v89re/zbRp07Jo0aK8/vrreeqpp3LJJZdk5513zrXXXtvk56ZOnZpk6VU3Tb19aJn6+vokS/97fsGCBe9qvmw4IgubtDlz5lS3l/2tyuos+0P67bffXq/znXfeeXnttdfykY98JF/5ylfW+fNvvPFGdfuMM85ITU1NfvCDH2Ty5MlZsGBB/vSnP1Xv55w+fXqOP/74zJ49e73mSuvT0tb76tx0003VW+NOOeWUomPTOrTE9b7rrrtm3Lhx+f73v5+5c+fmnHPOyaGHHpqDDjooX/va1zJ16tSce+65ee6553LAAQes1zlonVrael92y/PixYvzve99b5XHvPjiixk2bFj198t/j2za3uv1/oEPfCDnnntu7rrrrjz99NN5+umnM2LEiHz2s59NTU1N5s+fnzPOOCPXXXfdaue7LnN9N/NlwxNZ2KTNnz+/ur02fyPYvn37JKk+B2Jd/O53v8sNN9yQ2traXHPNNev1/Ii5c+dWt+fPn5/rr78+//qv/5r6+vq0a9cue+yxR4YNG5bTTz89ydK/7b/66qvX+Ty0Ti1tva/OL37xiyRJXV1dPve5zxUdm9ahpa73+++/PzfffPMq/+N60aJFuf3223PLLbd4/hYraGnr/Wtf+1p22GGHJMl1112Xk08+Of/93/+dhQsX5vXXX89NN92Ugw8+OHPnzs1mm2223nOldXov1/sJJ5yQiRMn5oc//GE+/elPp6GhIQ0NDfn85z+f22+/Pffdd191jX7729/O9OnTm5zvusx1fefLxkFkYZNWV1dX3V6btzQsu2yvQ4cO63SeBQsW5PTTT0+lUsm3vvWt7LXXXus20b9bfr577bVXTj755FUed+mll1b/kL7tttvW61y0Pi1tvTflySefzF/+8pckyXHHHZf3ve99RcendWiJ6/2cc87Jqaeemj//+c85/vjjM2bMmLz99tuZN29enn322Zx66qmZPHlyLrjggpx44olZvHjxep+L1qWlrff3ve99+eUvf5lu3bolWRrO995777Rv3z5du3bNl770pUyfPj2XXnpp9faKTp06rde5aH3eq/WeLF2rqwuJxxxzTPUNW++8806uv/76lY5ZNt91mWuyfvNl4yCysElb/l/Ya3NJ3rIrSdbmcr/lXXLJJfmf//mf1NfX5+KLL163SS5n+fmu7oGHW2+9dfbff/8kyR//+Eev+SRJy1vvTfHAW9ZGS1vvDzzwQH784x8nWfoaz3vuuScf/ehH07Fjx9TV1eVDH/pQbrjhhlx44YVJkrvvvjtXXXXVep+P1qWlrfck2W+//fKHP/whZ5111kpvGWpoaMjIkSPz//1//1/1Vostt9zyXZ2P1uO9Wu9r6/TTT6+GmMcff3yl/cvmuy5zTZpvvjS/ph/FDJuAurq6bL311nn99derD6Vqyptvvln9g2/ZQ6nW1pAhQ5IkRxxxRO6///5VHrNs7Llz52bEiBFJkm7duuWwww6rHlNfX199w9Ca5rBs/5IlS/LGG29k2223Xac50/q0tPW+KgsXLqxendW9e/d84hOfWKe5seloaet96NChSVJ91lZTvvvd7+YnP/lJ3n777dxwww35xje+sU7zpXVqaet9me222y5XXHFFrrjiikyfPj2zZ89O9+7dq1coTp06tXqrxZ577rlOc6X1eq/W+9rq1q1btt5668yaNWuVbxrq0aNHnnrqqcydOzdvvfXWah9+u+zhvNtss80Ktw7RsogsbPL22GOPPPHEE5k4cWIaGxubfA3cn//85+r2sqfir61lV5IMGzZshYe4rcqsWbPyT//0T0mSQw45ZIX/KNlzzz1zxx13JMkaLxNffv/qXm3HpqUlrfdVGTlyZPUB0F/84hfTtm3bdZobm5aWtN6Xva6zW7du1WdVrEpdXV323HPPPPXUUyvMG1rSel+VbbfddqW/EPr9739f3e7bt+86zZXW7b1Y7+tidbcU7bHHHrnrrruq82nqweWNjY156aWXkjTvXGl+bhdik/exj30sydK/cVn+X+b/aPnL/w488MBmn9eqHHzwwdXtl19+ebXHLvtDuq6uLltttVWzzouWoyWt91VxqxDroiWt92U/IDQ2Nq7x2EWLFq3wGUha1npfW8v+YilJPv/5z2/AmbCx2ZjW+8yZM6uvlN5+++1X2r9srv84n3/0zDPPVK+62dj/v8nqiSxs8o4//vjqdlN/K7NkyZLqD3ddunTJoYceuk7nqFQqa/zVs2fPJEnPnj2rX/vtb3+7wjgHH3xwttlmmyRL30DR1NUsr7zySv7whz8kWfqHdJs2/q/OUi1pvf+j119/PQ8++GCSZO+9987ee++9TvNi09OS1nuvXr2SLF3ny65qWZU33ngjzz///AqfgaRlrfe1MWHChOrtoUcccUR23XXXdR6D1uu9WO9r67rrrqu+8e2QQw5Zaf/HP/7x6i1wN954Y5Nvhxs+fHh1+4QTTig/Ud4zfvJik9e3b98cdNBBSZLrr78+Y8eOXemYH/3oR9X/6P3Wt75VfVXbMr/97W9TU1OTmpqaDBw4sNnm2rZt25x77rlJkldffTXf//73VzqmsbExX//617NkyZIkyRlnnNFs86HlaUnr/R/deuut1b/BdxULa6Mlrff+/ftXt88+++xVPrB8yZIl+eY3v1ndd8wxxzTbfGh5WtJ6T7LKZ1csM2XKlBx33HFpbGxM+/btc8UVVzTrXGh53ov1PmnSpDz33HOrncfIkSPzb//2b0mWvg3o1FNPXemYdu3a5Zvf/GaSpbeGXn755SsdM3bs2OqbiQ455JA0NDSs9rxs5CpA5dlnn6106NChkqSyxRZbVC699NLK2LFjK4899ljl9NNPrySpJKnsuuuuldmzZ6/0+VGjRlWPOeWUU9ZrDj179qwkqfTs2XO1x82bN6+y7777Vs83YMCAyq9+9avK73//+8rtt99e+chHPlLdd/TRR1eWLFmyXvOh9WpJ6315DQ0NlSSV2trayvTp09frvGx6Wsp6X7BgQWX33XevnqtPnz6V6667rvLUU09VnnnmmcrPf/7zFf587969e2XmzJnrNR9ar5ay3iuVSuWYY46pfPjDH65cdtlllccee6zy7LPPVh5++OHK+eefX+ncuXMlSaVNmzaVG2+8cb3mQevX3Ot92f6PfOQjlUsvvbTywAMPVMaNG1cZN25c5bbbbqt89rOfrdTU1FTHuPLKK5uc6+zZsyu77rpr9djTTz+98thjj1XGjh1bufTSSytbbLFFJUmlQ4cOleeee67gPyU2BJEF/u6+++6r/kt9Vb923XXXyosvvrjKz77XP3T+9a9/rey3335NznVZYFnVv1CgUmlZ671SqVReeOGFFdY2rIuWst4nTZpU2XvvvVf7Z3uSSq9evfxHOE1qKev9U5/61GrX+VZbbVUZMWLEes2BTUdzrvfl96/u1+abb1659tpr1zjXF198sbLLLrs0OU7nzp0r999//7v9R8JGwBPT4O/69++f//7v/85//ud/5oEHHsjUqVPTrl277LzzzvnsZz+bs846K5tvvvmGnmaSpa88fPLJJ3P99dfn1ltvzYQJE/LWW29l6623Tt++fTNw4ED3crJaLWm9J8lNN91U3XarEOuqpaz3nj17Zty4cRkxYkTuvPPOPPvss5k5c2YqlUq22mqr7LXXXjn++OPzpS99KR07dtzQ02Uj1VLW+3e+853stttueeKJJzJlypS8/vrr6dKlS3baaaccd9xxOe2009K1a9cNPU02cs253vfbb7/84he/yNixY/PMM89k2rRpmTVrVhobG7Pllltmzz33zOGHH57TTjst3bp1W+N4O++8c5577rlceeWVueOOOzJx4sQsXLgw9fX1Ofroo/Otb32r+kwjWraaSqWJJ+8AAAAAsNY8+BYAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKAAkQUAAACgAJEFAAAAoACRBQAAAKCA/x9KSqY5phTkKQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 428, + "width": 556 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = base\n", + "df = df.sort_values('before_mix')\n", + "plt.plot(df['before_mix'],df['before_profit'])" + ] + }, + { + "cell_type": "markdown", + "id": "b3774c32-ec43-4ffa-8f6b-f2c722641bd9", + "metadata": {}, + "source": [ + "# Balance check" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ad5c3a7-74cc-49bd-8373-4b512a2f8e22", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "787eb355-7d62-4dc8-9f22-7776d96af272", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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qlWrIiKid+/eUVxcvNd9egdfSxYuXBj9+vWr7zIAAAAgGXPnzo2+ffvudT8uqwEAAACS5syRWnLggQfmtufOnRsHH3xwPVYDAAAATdPKlStzV27s+l58bwhHasmu9xg5+OCDo6SkpB6rAQAAgKavtu736bIaAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpeQ1H5s+fHz/60Y9i8ODBUVJSEi1atIjWrVtH9+7d46KLLopZs2bVyjhjx46NgoKCKn09//zztTImAAAA0DQU5qvjk046KWbOnLnH/2/dujWWLFkSS5YsiQkTJsSFF14Yv/nNb6KoqChfpQAAAACUK2/hyPvvvx8REZ07d46vfOUrceKJJ8YhhxwS27dvjzlz5sQtt9wS7733Xtx7772xbdu2+N3vflcr4y5cuLDC/YcddlitjAMAAAA0DXkLR3r06BE//vGP49xzz43mzZvvtu+4446Lb3zjG9G/f/9YvHhxTJo0KS6//PI46aST9nrcz33uc3vdBwAAAJCOvN1z5Mknn4wRI0bsEYzsdMABB8Qtt9yS+/dDDz2Ur1IAAAAAypW3M0eqYuDAgbntt956qx4rSU+2I4vNG7bVdxkAAAA0IMWt9omCZgX1XUadq9dwZMuWLbnt8s4wIT82b9gWd/1n7XxaEAAAAE3DN28+IVrul94HptRrODJjxozcds+ePWulz8GDB8ef/vSnWLt2bbRt2zZ69eoVp512WowePTratWtX435XrFhR4f6VK1fWuG8AAACg/tRbOLJjx4746U9/mvv3iBEjaqXfZ555Jre9atWqmDFjRsyYMSNuuummmDBhQgwbNqxG/Xbp0qVW6gMAAAAalnoLR2699daYO3duREScc845ceyxx+5Vf717946zzz47+vXrF507d45t27bFm2++GRMnToypU6fG2rVr49xzz43JkyfHkCFDauNHAAAAAJqAgizLsroedMaMGTFo0KAoLS2Njh07xsKFC6Njx4417m/nJTTlGTduXFx++eUREdG5c+d46623ori4uFpjVOWymn79+kVExPLly6OkpKRa/dc1N2QFAADgnzWGG7KuWLEid3VHbb3/rvMzR1577bUYPnx4lJaWRnFxcfz+97/fq2AkIioMRiIiRo8eHfPmzYvx48fH+++/Hw8//HB8/etfr9YYDT3sqK6CZgVJ3mQHAAAA/lmzuhzsnXfeicGDB8dHH30UzZs3j/vvvz9OOumkOhl79OjRue1dbwQLAAAApK3OwpH3338/Bg0aFO+//34UFBTEXXfdVeObo9ZEr169ctvvvfdenY0LAAAANGx1Eo6sXr06Tj311Hj77bcjIuL222+PCy+8sC6GzikoaNjXTAEAAAD1I+/hyMcffxxf+tKXYtGiRRER8dOf/jSuvPLKfA+7h53jR3x6U1YAAACAiDyHIxs3bowzzjgjXn311YiI+P73vx/XXXddPocs17hx43LbAwYMqJcaAAAAgIYnb+HI1q1bY/jw4TF79uyIiLjqqqvihhtuqHY/EyZMiIKCgigoKIixY8fusX/hwoWxdOnSCvu444474s4774yIiE6dOsXw4cOrXQcAAADQNOXto3y/9rWvxdSpUyMi4uSTT46LL744/vrXv5bbvqioKLp3717tcV555ZW45JJLYuDAgTFkyJDo3bt3dOjQIUpLS+ONN96IiRMn5upo3rx53HHHHdGqVaua/VAAAABAk5O3cOSRRx7JbT/33HPxL//yLxW279q1ayxbtqxGY23fvj2effbZePbZZ8tt06FDhxg/fnwMHTq0RmMAAAAATVPewpG6cvrpp8f48eNjzpw5sWDBgvjggw9izZo1kWVZtG/fPo4++ug47bTTYtSoUdGmTZv6LhcAAABoYAqyLMvqu4imYMWKFdGlS5eIiFi+fHmUlJTUc0UAAADQ9OTj/XfeP8oXAAAAoCETjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkrrO8CqB87dmTx0cat9V0GAAAADUi7fYuiWbOC+i6jzglHEvXRxq1x7A3P1ncZAAAANCCv/Neg6NC6RX2XUedcVgMAAAAkTTgCAAAAJE04AgAAACTNPUcS1W7fonjlvwbVdxkAAAA0IO32LarvEuqFcCRRzZoVJHmTHQAAAPhnLqsBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJKW13Bk/vz58aMf/SgGDx4cJSUl0aJFi2jdunV07949Lrroopg1a1atjzlp0qQYPHhwdOrUKYqLi6Nr165xwQUXxJw5c2p9LAAAAKDxK8iyLMtHxyeddFLMnDmz0nYXXnhh/OY3v4mioqK9Gm/Tpk3x5S9/OZ566qky9zdr1izGjBkT119//V6NU54VK1ZEly5dIiJi+fLlUVJSkpdxAAAAIGX5eP+dtzNH3n///YiI6Ny5c1x11VXx0EMPxdy5c2POnDnxf/7P/4nPfOYzERFx7733xqhRo/Z6vG9+85u5YGTgwIHx2GOPxdy5c2P8+PFxxBFHxI4dO2Ls2LFxxx137PVYAAAAQNORtzNHzjzzzLjwwgvj3HPPjebNm++xf/Xq1dG/f/9YvHhxRETMmDEjTjrppBqN9dxzz8Upp5wSERFDhw6NRx99dLcxV69eHccee2y8++670bZt23j77bejXbt2NRqrPM4cAQAAgPxrVGeOPPnkkzFixIgyg5GIiAMOOCBuueWW3L8feuihGo/185//PCIiCgsL41e/+tUeYx5wwAFx0003RUTE2rVr484776zxWAAAAEDTUq+fVjNw4MDc9ltvvVWjPtavXx/Tpk2LiIhBgwaVmxidc8450aZNm4iIePTRR2s0FgAAAND01Gs4smXLltx2eWeYVGbevHmxdevWiIgYMGBAue2KioriuOOOy33Ptm3bajQeAAAA0LQU1ufgM2bMyG337NmzRn0sWrQot92jR48K2/bo0SOmTp0apaWlsWTJkujVq1eVx1mxYkWF+1euXFnlvgAAAICGo97CkR07dsRPf/rT3L9HjBhRo352DS0quwnLzhu2RHx605bqhCO7fi8AAADQdNTbZTW33nprzJ07NyI+vR/IscceW6N+1q9fn9tu3bp1hW1btWqV2/7kk09qNB4AAADQtNTLmSMzZsyI73znOxER0bFjx/i///f/1rivzZs357aLiooqbNuiRYvc9qZNm6o1zvLlyyvcv3LlyujXr1+1+gQAAADqX52HI6+99loMHz48SktLo7i4OH7/+99Hx44da9xfcXFxbnvnjVnLs+sNYFu2bFmtcWrjc5MBAACAhqdOL6t55513YvDgwfHRRx9F8+bN4/7774+TTjppr/rcb7/9ctuVXSqzYcOG3HZll+AAAAAAaaizcOT999+PQYMGxfvvvx8FBQVx1113xbBhw/a6313P6KjsE2V2vTTGDVYBAACAiDoKR1avXh2nnnpqvP322xERcfvtt8eFF15YK33v+okzb7zxRoVtd+4vLCyMI488slbGBwAAABq3vIcjH3/8cXzpS1+KRYsWRUTET3/607jyyitrrf++ffvmbsQ6Y8aMcttt3bo1Xnrppdz37LPPPrVWAwAAANB45TUc2bhxY5xxxhnx6quvRkTE97///bjuuutqdYz99tsvTjnllIiIePbZZ8u9tOaRRx6JdevWRUTE8OHDa7UGAAAAoPHKWziydevWGD58eMyePTsiIq666qq44YYbqt3PhAkToqCgIAoKCmLs2LFltvmP//iPiIgoLS2NK6+8MrZv377b/tWrV+dCmbZt28Yll1xS7ToAAACApilvH+X7ta99LaZOnRoRESeffHJcfPHF8de//rXc9kVFRdG9e/cajXXyySfHV7/61bj//vvjiSeeiFNPPTWuvvrq6Ny5cyxcuDBuvPHGePfddyMi4qabbop27drVaBwAAACg6clbOPLII4/ktp977rn4l3/5lwrbd+3aNZYtW1bj8e66665Yt25dPPXUUzF9+vSYPn36bvubNWsWP/jBD+Kyyy6r8RgAAABA01NnH+Wbby1btowpU6bExIkT49RTT42OHTtGUVFRdOnSJc4///yYNWtWuZflAAAAAOkqyLIsq+8imoIVK1ZEly5dIiJi+fLlUVJSUs8VAQAAQNOTj/ffTebMEQAAAICaEI4AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJE44AAAAASROOAAAAAEkTjgAAAABJy2s48uGHH8aTTz4ZY8aMiSFDhsQBBxwQBQUFUVBQEKNGjaq1ccaOHZvrt7Kv559/vtbGBQAAABq/wnx2ftBBB+WzewAAAIC9ltdwZFeHHHJI9OjRI6ZOnZrXcRYuXFjh/sMOOyyv4wMAAACNS17DkTFjxkTfvn2jb9++cdBBB8WyZcvyHk587nOfy2v/AAAAQNOS13Dkhz/8YT67BwAAANhrPq0GAAAASJpwBAAAAEhand2Qta4MHjw4/vSnP8XatWujbdu20atXrzjttNNi9OjR0a5duxr3u2LFigr3r1y5ssZ9AwAAAPWnyYUjzzzzTG571apVMWPGjJgxY0bcdNNNMWHChBg2bFiN+u3SpUttlQgAAAA0IE0mHOndu3ecffbZ0a9fv+jcuXNs27Yt3nzzzZg4cWJMnTo11q5dG+eee25Mnjw5hgwZUt/lAgAAAA1EQZZlWV0NtutH+Y4cOTImTJhQK/3uvISmPOPGjYvLL788IiI6d+4cb731VhQXF1drjKpcVtOvX7+IiFi+fHmUlJRUq38AAACgcitWrMhd3VFb77+bxJkjFQUjERGjR4+OefPmxfjx4+P999+Phx9+OL7+9a9XawxhBwAAADRNyXxazejRo3PbM2bMqMdKAAAAgIYkmXCkV69eue333nuvHisBAAAAGpJkwpGCgoL6LgEAAABogJIJRxYtWpTb7ty5cz1WAgAAADQkyYQj48aNy20PGDCgHisBAAAAGpIGH45MmDAhCgoKoqCgIMaOHbvH/oULF8bSpUsr7OOOO+6IO++8MyIiOnXqFMOHD89HqQAAAEAjlNeP8p01a9ZuwcXq1atz20uXLo0JEybs1n7UqFHVHuOVV16JSy65JAYOHBhDhgyJ3r17R4cOHaK0tDTeeOONmDhxYkydOjUiIpo3bx533HFHtGrVqkY/DwAAAND05DUcufPOO+Oee+4pc9/s2bNj9uzZu/1fTcKRiIjt27fHs88+G88++2y5bTp06BDjx4+PoUOH1mgMAAAAoGnKazhSF04//fQYP358zJkzJxYsWBAffPBBrFmzJrIsi/bt28fRRx8dp512WowaNSratGlT3+UCAAAADUxBlmVZfRfRFKxYsSK6dOkSERHLly+PkpKSeq4IAAAAmp58vP9u8DdkBQAAAMgn4QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJC0vIYjH374YTz55JMxZsyYGDJkSBxwwAFRUFAQBQUFMWrUqLyMOWnSpBg8eHB06tQpiouLo2vXrnHBBRfEnDlz8jIeAAAA0LgV5rPzgw46KJ/d72bTpk3x5S9/OZ566qnd/v/dd9+NiRMnxqRJk2LMmDFx/fXX11lNAAAAQMNXZ5fVHHLIITF48OC89f/Nb34zF4wMHDgwHnvssZg7d26MHz8+jjjiiNixY0eMHTs27rjjjrzVAAAAADQ+eT1zZMyYMdG3b9/o27dvHHTQQbFs2bI47LDDan2c5557Lu6///6IiBg6dGg8+uij0bx584iI6Nu3b5x11llx7LHHxrvvvhvXXXddfOUrX4l27drVeh0AAABA45PXM0d++MMfxplnnpn3y2t+/vOfR0REYWFh/OpXv8oFIzsdcMABcdNNN0VExNq1a+POO+/Maz0AAABA49HoP61m/fr1MW3atIiIGDRoUJSUlJTZ7pxzzok2bdpERMSjjz5aZ/UBAAAADVujD0fmzZsXW7dujYiIAQMGlNuuqKgojjvuuNz3bNu2rU7qAwAAABq2vN5zpC4sWrQot92jR48K2/bo0SOmTp0apaWlsWTJkujVq1eVx1mxYkWF+1euXFnlvgAAAICGo9GHI7uGFuVdUrNTly5dctvLly+vVjiy6/cCAAAATUejv6xm/fr1ue3WrVtX2LZVq1a57U8++SRvNQEAAACNR6M/c2Tz5s257aKiogrbtmjRIre9adOmao2zfPnyCvevXLky+vXrV60+AQAAgPrX6MOR4uLi3PbOG7OWZ8uWLbntli1bVmucyi7ZAQAAABqnRn9ZzX777ZfbruxSmQ0bNuS2K7sEBwAAAEhDow9Hdj2jo7JPlNn10hg3WAUAAAAimkA4susnzrzxxhsVtt25v7CwMI488si81gUAAAA0Do0+HOnbt2/uRqwzZswot93WrVvjpZdeyn3PPvvsUyf1AQAAAA1bow9H9ttvvzjllFMiIuLZZ58t99KaRx55JNatWxcREcOHD6+z+gAAAICGrcGHIxMmTIiCgoIoKCiIsWPHltnmP/7jPyIiorS0NK688srYvn37bvtXr14d1113XUREtG3bNi655JK81gwAAAA0Hnn9KN9Zs2bF0qVLc/9evXp1bnvp0qUxYcKE3dqPGjWqRuOcfPLJ8dWvfjXuv//+eOKJJ+LUU0+Nq6++Ojp37hwLFy6MG2+8Md59992IiLjpppuiXbt2NRoHAAAAaHryGo7ceeedcc8995S5b/bs2TF79uzd/q+m4UhExF133RXr1q2Lp556KqZPnx7Tp0/fbX+zZs3iBz/4QVx22WU1HgMAAABoehr8ZTVV1bJly5gyZUpMnDgxTj311OjYsWMUFRVFly5d4vzzz49Zs2aVe1kOAAAAkK6CLMuy+i6iKVixYkV06dIlIiKWL18eJSUl9VwRAAAAND35eP/dZM4cAQAAAKgJ4QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJC0wvougPqR7dgR29eure8yAAAAaECat20bBc3SO49COJKo7WvXxpJ/7V/fZQAAANCAHPni7Chs376+y6hz6cVBAAAAALsQjgAAAABJE44AAAAASXPPkUQ1b9s2jnxxdn2XAQAAQAPSvG3b+i6hXghHElXQrFmSN9kBAACAf+ayGgAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBpwhEAAAAgacIRAAAAIGnCEQAAACBphfVdAPVkx46ITf+o7yoAAABoSFq2j2iW3nkUwpFUbfpHxM1H1HcVAAAANCT/+VZEqwPqu4o6l14cBAAAALAL4QgAAACQNOEIAAAAkDT3HElVy/afXksGAAAAO7VsX98V1AvhSKqaNUvyJjsAAADwz1xWAwAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACRNOAIAAAAkTTgCAAAAJE04AgAAACStzsKRv/3tb3HttddGjx49olWrVtG+ffvo27dv3HzzzbFx48a96nvChAlRUFBQpa8JEybUzg8EAAAANAmFdTHI5MmT44ILLoh169bl/m/jxo0xf/78mD9/ftx5550xZcqU6NatW12UAwAAAJCT93BkwYIFcd5558WmTZuidevW8d3vfjcGDhwYmzZtivvvvz9+85vfxOLFi+OMM86I+fPnx3777bdX4/3xj3+Mzp07l7u/pKRkr/oHAAAAmpa8hyNXXXVVbNq0KQoLC2Pq1Klx/PHH5/adfPLJceSRR8a3v/3tWLx4cdxyyy0xduzYvRqve/fuceihh+5d0QAAAEAy8nrPkblz58bMmTMjIuLiiy/eLRjZ6dprr42ePXtGRMRtt90W27Zty2dJAAAAALvJazjy2GOP5bYvuuiisgto1iwuvPDCiIhYu3ZtTJ8+PZ8lAQAAAOwmr+HIrFmzIiKiVatWceyxx5bbbsCAAbnt2bNn57MkAAAAgN3k9Z4jr7/+ekREdOvWLQoLyx+qR48ee3xPTV100UXx5ptvxurVq6NNmzbRrVu3GDRoUHzrW9+Kz3zmMzXud8WKFRXuX7lyZY37BgAAAOpP3sKRzZs3x+rVqyOi8k+IadeuXbRq1So2bNgQy5cv36txn3/++dz2mjVrYs2aNfHyyy/HLbfcEr/4xS9i9OjRNeq3S5cue1UXAAAA0DDlLRxZv359brt169aVtt8ZjnzyySc1Gu/www+Pc845J44//vhckPH222/Hww8/HA899FBs3rw5Lr/88igoKIjLLrusRmMAAAAATU9ezxzZqaioqNL2LVq0iIiITZs2VXus4cOHx8iRI6OgoGC3/+/bt2+cd9558eSTT8Y555wT27Zti2uuuSbOOuus6NSpU7XGqOyMlpUrV0a/fv2qXTsAAABQv/J2Q9bi4uLc9tatWyttv2XLloiIaNmyZbXH2n///fcIRnZ15plnxpgxYyIiYuPGjTF+/Phqj1FSUlLh18EHH1ztPgEAAID6l7dwZL/99sttV+VSmQ0bNkRE1S7BqYnLLrssF6DMmDEjL2MAAAAAjU9ezxzp0KFDRFT+SS8fffRRLhzJ141PO3bsmKvnvffey8sYAAAAQOOTt3AkIqJXr14REbF06dIoLS0tt90bb7yR2+7Zs2fe6qno0hsAAAAgTXkNR0444YSI+PSSmVdeeaXcdrte5tK/f/+81LJq1arcRwt37tw5L2MAAAAAjU9ew5Gzzz47t3333XeX2WbHjh1x7733RkRE27ZtY+DAgXmp5Y477ogsyyIiYsCAAXkZAwAAAGh88hqO9OvXL0488cSIiBg/fnzMmTNnjza33HJLvP766xERcdVVV8U+++yz2/7nn38+CgoKoqCgIEaNGrXH9y9btiwWLFhQYR1PPvlk/OhHP4qITz8N56KLLqrJjwMAAAA0QYX5HuC2226L/v37x6ZNm2Lw4MHxve99LwYOHBibNm2K+++/P+64446IiOjevXtce+211e5/2bJlMXDgwDj++ONj6NChcfTRR0fHjh0jIuLtt9+Ohx56KB566KHcWSM///nP4zOf+Uzt/YAAAABAo5b3cOSYY46JBx54IC644IJYt25dfO9739ujTffu3WPKlCm7ffxvdc2ZM6fMM1N22nfffePWW2+Nyy67rMZjAAAAAE1P3sORiIihQ4fGX/7yl7jttttiypQpsWLFiigqKopu3brFV77ylfi3f/u32HfffWvU97HHHhv33XdfzJkzJ+bPnx8rV66M1atXR2lpabRr1y4++9nPximnnBKXXHJJ7owSAAAAgJ0Ksp3Xm7BXVqxYEV26dImIiOXLl0dJSUk9VwQAAABNTz7ef+f1hqwAAAAADZ1wBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASFqdhSN/+9vf4tprr40ePXpEq1aton379tG3b9+4+eabY+PGjbU2ztNPPx3Dhw+PkpKSaNGiRZSUlMTw4cPj6aefrrUxAAAAgKajIMuyLN+DTJ48OS644IJYt25dmfu7d+8eU6ZMiW7dutV4jB07dsRll10W48ePL7fNJZdcEuPGjYtmzWo/E1qxYkV06dIlIiKWL18eJSUltT4GAAAApC4f77/zfubIggUL4rzzzot169ZF69at48Ybb4wXX3wxpk2bFpdeemlERCxevDjOOOOMWL9+fY3H+f73v58LRo455piYNGlSzJ07NyZNmhTHHHNMRETceeed8V//9V97/0MBAAAATUbezxw56aSTYubMmVFYWBgvvPBCHH/88bvtv/nmm+Pb3/52RERcf/31MXbs2GqPsXjx4vjsZz8bpaWl0adPn3jhhReiZcuWuf0bN26MAQMGxPz586OwsDBef/31vTpLpSzOHAEAAID8a3RnjsydOzdmzpwZEREXX3zxHsFIRMS1114bPXv2jIiI2267LbZt21btcX7xi19EaWlpRETcfvvtuwUjERH77rtv3H777RERUVpaGrfeemu1xwAAAACapryGI4899lhu+6KLLiq7gGbN4sILL4yIiLVr18b06dOrNUaWZfH4449HRESPHj3iuOOOK7PdcccdF0cddVRERDz++ONRB7daAQAAABqBwnx2PmvWrIiIaNWqVRx77LHlthswYEBue/bs2TF48OAqj/HOO+/E+++/v0c/5Y3z5ptvxnvvvRfLli2Lww47rMrjNDU7sh2xdsva+i4DAACABqRti7bRrKDOPti2wchrOPL6669HRES3bt2isLD8oXr06LHH91TVokWLyuynKuNUJxxZsWJFhftXrlxZ5b4agrVb1saAByoOkwAAAEjLjPNmRPvi9vVdRp3LWziyefPmWL16dUREpTdHadeuXbRq1So2bNgQy5cvr9Y4u4YWlY2z84YtEVHtcXb9XgAAAKDpyNu5Mrt+LG/r1q0rbd+qVauIiPjkk0/yNs7OMWoyDgAAANA05fXMkZ2Kiooqbd+iRYuIiNi0aVPextk5Rk3GqexMk5UrV0a/fv2q1ScAAABQ//IWjhQXF+e2t27dWmn7LVu2RETs8TG8tTnOzjFqMk5tfG5yQ9K2RduYcd6M+i4DAACABqRti7b1XUK9yFs4st9+++W2q3IJy4YNGyKiapfg1HScnWPUZJympllBsyRvsgMAAAD/LG/3HCkuLo4OHTpEROWf9PLRRx/lgovq3vh01zM6Khtn10tj3GAVAAAAiMhjOBIR0atXr4iIWLp0aZSWlpbb7o033sht9+zZs0Zj/HM/tT0OAAAA0DTlNRw54YQTIuLTy1leeeWVctvNmPH/7n3Rv3//ao1x2GGHRefOnffopywvvPBCRER85jOfiUMPPbRa4wAAAABNU17DkbPPPju3fffdd5fZZseOHXHvvfdGRETbtm1j4MCB1RqjoKAghg0bFhGfnhny0ksvldnupZdeyp05MmzYsCgoKKjWOAAAAEDTlNdwpF+/fnHiiSdGRMT48eNjzpw5e7S55ZZb4vXXX4+IiKuuuir22Wef3fY///zzUVBQEAUFBTFq1Kgyx7n66qujefPmERHx7//+73t8TO+mTZvi3//93yMiorCwMK6++uq9+bEAAACAJiSv4UhExG233RYtW7aM0tLSGDx4cPzkJz+Jl156KaZPnx6jR4+Ob3/72xER0b1797j22mtrNEb37t3jP//zPyMiYv78+dG/f/944IEHYv78+fHAAw9E//79Y/78+RER8Z//+Z9x5JFH1s4PBwAAADR6efso352OOeaYeOCBB+KCCy6IdevWxfe+97092nTv3j2mTJmy28fyVteNN94YH374Ydx1112xYMGC+OpXv7pHm4svvjhuuOGGGo8BAAAAND15P3MkImLo0KHxl7/8Ja655pro3r177LvvvtG2bdvo06dP3HTTTbFgwYLo1q3bXo3RrFmzGD9+fEyZMiWGDRsWnTt3jqKioujcuXMMGzYsnnrqqbjzzjujWbM6+ZEBAACARqIgy7KsvotoClasWBFdunSJiIjly5dHSUlJPVcEAAAATU8+3n87jQIAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABIWmF9F9BUlJaW5rZXrlxZj5UAAABA07Xre+5d34vvDeFILVm1alVuu1+/fvVYCQAAAKRh1apVceihh+51Py6rAQAAAJJWkGVZVt9FNAWbN2+OhQsXRkTEgQceGIWFDf+knJUrV+bOcpk7d24cfPDB9VwR1WUOGzfz1/iZw8bPHDZ+5rBxM3+Nnzls/BrjHJaWluau3ujdu3cUFxfvdZ8N/x18I1FcXBx9+/at7zJq7OCDD46SkpL6LoO9YA4bN/PX+JnDxs8cNn7msHEzf42fOWz8GtMc1salNLtyWQ0AAACQNOEIAAAAkDThCAAAAJA04QgAAACQNOEIAAAAkDThCAAAAJA04QgAAACQtIIsy7L6LgIAAACgvjhzBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacAQAAABImnAEAAAASJpwBAAAAEiacKSR++STT+KFF16In//85zFixIg47LDDoqCgIAoKCuLQQw/Ny5gvvvhiXHDBBdG1a9coLi6OTp06xZe+9KWYNGlStfqZNGlSDB48ODp16hTFxcXRtWvXuOCCC2LOnDl5qbuh27hxY/zsZz+Lvn37Rvv27aNVq1bRo0ePuPbaa+Nvf/vbXvd/6KGH5n43qvq1bNmyPfoZO3Zslb//+eef3+u6G5N8z+GyZcuqfOxHjRpVpT6tw93lew537NgRL7zwQnzve9+LL37xi9GpU6coKiqKNm3axOc+97m44oor4i9/+Uul/aS2Dv/2t7/FtddeGz169IhWrVpF+/bto2/fvnHzzTfHxo0ba22cp59+OoYPHx4lJSXRokWLKCkpieHDh8fTTz9d5T5KS0vj17/+dZx44olx4IEHRsuWLeOII46I0aNHx2uvvVZrtTYm+Zy/jRs3xiOPPBLf+ta3om/fvtGuXbvYZ599okOHDnH88cfH2LFj4+9//3ul/Xzxi1+s8ppKUT7ncMKECVU+9hMmTKi0v3w/jjdW+ZrD6rw2qew9inW4pw8//DCefPLJGDNmTAwZMiQOOOCAar/Wq67aeG3YaNdhRqP2xS9+MYuIMr+6du1a6+Ndf/31WbNmzcod84wzzsg2bdpUYR8bN27MTj/99HL7aNasWTZ27Nhar70hW7JkSXbkkUeWe0zatGmTTZ48ea/G6Nq1a7n9l/W1//77lzmX119/fZX7mD59+l7V3JjUxRy+8847VT72I0eOrLAv63BPdTGHXbp0qXTumjVrln3729/OduzYUW4/Ka3DJ554ImvTpk25P1/37t2zJUuW7NUY27dvzy6++OIKj+Mll1ySbd++vcJ+Vq1alfXt27fcPlq0aJH95je/2ataG5t8zt+f//znrHXr1pWugTZt2mT3339/hX0NGDCgymsqNfleg3fffXeVj/3dd99dYV918TjeGOVzDqvz2mTn1+DBg8vsyzrcU0XHoLLXetVVW68NG/M6TOc3q4na9UGkffv22eDBg3MvFGo7HPn1r3+dG+uII47Ixo8fn82dOzd77LHHsoEDB+b2fe1rX6uwn69+9au5tgMHDswee+yxbO7cudn48eOzI444Irdv3LhxtVp/Q7Vu3bqse/fuuZ/70ksvzaZNm5a9+OKL2Y033pibz3333TdbsGBBjcd58803s4ULF1b4deutt+5WR1l2fVNWWX+ffPJJjettTOpqDnd9AXLDDTdUeOxXrFhRYV/W4e7qag6bN2+eRUTWrVu37LrrrsueeOKJbP78+dnMmTOzH/3oR1m7du1yNXz3u98tt59U1uGrr76atWzZMouIrHXr1tmNN96Yvfjii9m0adOySy+9dLcX9uvWravxON/5zndyfR1zzDHZpEmTsrlz52aTJk3KjjnmmCrNSWlpaXbCCSfk2p5zzjnZ008/nb388svZf//3f2cdO3bMvbh86qmnalxrY5Lv+Zs5c2auj/79+2c/+clPsmeeeSZ79dVXsz/+8Y/Z6NGjc3/Qad68eYXHfefrqT59+lS6plJSF2tw13Dkj3/8Y4XH/qOPPiq3n7p6HG9s8j2HW7durXTNLFy4MDv//PNzY02cOLHMvqzDPe0aKhxyyCHZ4MGD8xaO1MZrw8a+DoUjjdy4ceOy3/3ud7ulvTvPEKjNcGTNmjXZ/vvvn1uYq1at2m1/aWlpNnTo0NxCKO8vldOmTcu1GTp0aFZaWrrb/lWrVmWHHHJIFhFZ27Zts3/84x+19jM0VD/4wQ9yx+RnP/vZHvtnz56dFRYWZhGRDRgwIK+1jBgxIlfLzJkzy2yz65syPlVXc7hrOFLZX88qYh3uqa7m8Pjjj8/+8Ic/lHtWyNKlS7MDDzwwi4issLAwe+utt8psl8o6PPHEE3PH4sUXX9xj/89+9rPccbj++utrNMabb76Zm9s+ffpkGzdu3G3/hg0bsj59+uTqKO+vq+PHj8/VcsUVV+yxf8mSJbm/3Hbr1i3btm1bjeptTPI9f7Nnz85GjBiRvfbaa+W2eeyxx7KCgoLcH3bKW3s735Tl+3m2samLNbhrOPLOO+/UuNaG9HqqIamLOaxMaWlp1rlz5ywisv3222+Px9mdrMM9jRkzJps8eXL297//Pcuy3V8L1mY4UluvDRv7Omzar6oSlY9w5Kabbsr9ok+aNKnMNsuXL8/9VfT0008vs82QIUNyD9DLly8vs82kSZMqXFRNydatW3OhU8+ePcs9ZXv06NG5YzJ37ty81LJ27dqsuLg4i4js8MMPL7ddKm/Kqqou57C2whHrcHcNaR1mWZbdfvvtuXFuueWWMtuksA5ffvnl3M84evToMtts374969mzZ+7F2tatW6s9zre+9a3cOHPmzCmzzZw5cyoMPrIsy9XRvn37bMOGDWW2+clPfpLr58EHH6x2rY1JXc1fVZx77rm5Wl555ZUy23hTtqe6msPaCEca2uN4Q9FQ1uEf/vCHXB0XXXRRue2sw8rlKxypjdeGTWEduiErVfLYY49FRESbNm3inHPOKbNNSUlJDBo0KCIipk2bFuvXr99t//r162PatGkRETFo0KAoKSkps59zzjkn2rRpExERjz76aG2U32BNnz49Pv7444iIGDlyZDRrVvaS3PWGS/k6Jg8++GBs3rw5IiIuvPDCvIzRFDWkOawK63BPDW0OBw4cmNt+66238jZOQ7fzeSci4qKLLiqzTbNmzXKPV2vXro3p06dXa4wsy+Lxxx+PiIgePXrEcccdV2a74447Lo466qiIiHj88ccjy7Ld9i9evDhef/31iIgYMWJE7LvvvmX201AeB+pCXcxfVVlTNdOQ5rAyDe1xvKFoKHN477335rZHjhxZ6/2zd2rrtWFTWIfCESq1devWmDt3bkREHH/88VFUVFRu2wEDBkRExJYtW2L+/Pm77Zs3b15s3bp1t3ZlKSoqyr1AnTdvXmzbtm2v6m/IZs2alduu6Jj06dMn92J79uzZeall5xNXQUFBfOMb38jLGE1RQ5rDqrAO99TQ5nDLli257ebNm+dtnIZu57y0atUqjj322HLb7Tpn1Z2Xd955J95///09+qlonPfee2+PT/Kq6u9Qp06donv37jWqtbGpi/mrKmuqZhrSHFamoT2ONxQNYQ7Xr1+fC2kOPfTQOOmkk2q1f/Zebb02bArrUDhCpRYvXhzbt2+PiE//slaRXffv/CvaTosWLSqzXUX9lJaWxpIlS6pVb2NS1WNSWFgY3bp1i4g9j2tteOedd3IPTieccEIcfvjhVfq+wYMHR8eOHaOoqCg6duwYX/ziF+OnP/1pfPTRR7VeY0NVX3N4++23R7du3aK4uDj233//+OxnPxuXX355vPrqq7VS7677rcNP5Xsd7jRjxozcds+ePStt31TX4c5j3K1btygsLCy3XUXPO5WpyXooa5ya9LN8+fLYsGFDlWttbOpi/qqqOmvqjTfeiC984QvRtm3bKC4ujpKSkhg2bFjce++9TTokLkt9zOFFF10UnTt3jqKiojjggAPiuOOOi//6r/+K9957r8Lva2iP4w1FQ1iHDz30UO6jgr/xjW9U6WN4rcO6VVuvDZvCOhSOUKkVK1bktss7zWqnLl265LaXL1+el36akp3HpFWrVtG2bdsK2+48JqtWrdrtr2C14d57782dJl6dS2qeeeaZWLVqVWzbti1WrVoVM2bMiO9+97tx+OGH505Vb+rqaw5fffXVeOutt2LLli2xbt26WLRoUYwbNy6OPfbYuPzyy8vt3zrcU0NZhxERGzdujF/84hcREdGiRYsYNmxYpd/TFNfh5s2bY/Xq1RFR+e9pu3btolWrVhFR/d/T+nx+y7Jst+9rSupq/qriz3/+c0yZMiUiInr37l1pOPLBBx/E3Llz4+OPP44tW7bEe++9F0888USMHDkyPv/5zze4F/L5Ul9z+Pzzz8fKlStj27ZtsWbNmnj55ZfjxhtvjG7dusW4cePK/b6G9DjeUDSUdbjrJTVVfY1pHdat2n4ubMzrsPwIEf5/u947pHXr1hW23fnAGhHxySef5KWfpmTnManseETseUxatGhRa3X89re/jYiIli1bxogRIypt37t37zj77LOjX79+0blz59i2bVu8+eabMXHixJg6dWqsXbs2zj333Jg8eXIMGTKk1upsiOp6Dtu2bRvDhw+PL37xi3HkkUdGcXFxrFy5MqZOnRrjx4+PTz75JMaNGxfr16+PiRMnlltvVWq2DveUz3UYEXHdddfFu+++GxERV155ZXTu3Lnctk15HVbn9zTi03nZsGFDtX9PPb/lR13NX2W2bNkSl1xySe7s1xtvvLHcts2aNYtTTjklTj/99Dj66KOjQ4cOsX79+nj11Vdj3Lhx8frrr8eiRYti4MCBMXfu3DjkkENqtdaGpq7n8PDDD49zzjknjj/++NybprfffjsefvjheOihh2Lz5s1x+eWXR0FBQVx22WXl1tsQHscbioawDt99993cmVv/+q//mjtboDzWYf2o7efCxrwOhSNUaudNOiOiwvuNRMRuv9ibNm3KSz9Nyc5jUtnxiMjfMXnxxRdzN6gbNmxY7kZL5bn66qtj7Nixe/z/F77whbjwwgtj3Lhxcfnll8f27dvjkksuibfeeiuKi4trrd6Gpi7nsHPnzvHee+/tcbPHY445Jk4//fS48sorY9CgQfHuu+/G7373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q1atsojI9t9//2z+/Pl7U3qZtm3blqs1IrJ333231sdoaOpyDitzww035Gr53//7f++xv6E9FzcU9TWHw4cPz427YMGCve5vpxTX4T975513cj//yJEja63f2nht2BTWoXCkCapuOLLrIhswYECZbdasWZP7Ze/atWu2evXq3faXlpZmQ4cOzfUzffr0MvuZNm1ars1ZZ52VlZaW7rZ/1apV2SGHHJJ7gP7HP/5RpZ+hMfvBD35Q4QPNiy++mBUWFlY4P1mW5fqo6rwfe+yxuQfBDz74oErf85e//CVbsmRJhW3GjRuXq6VTp07ZJ598UqW+G7O6msNHH3203CeaLMuyJUuW5NZPRGQPP/xwme2swz3V1Rx+9NFH2ec///m9CiZTWocnnnhi7nHqxRdf3GP/z372s9zPef311++xf/r06ZW+iHzzzTdzwX6fPn2yjRs37rZ/48aNWZ8+fXJ1LF68uMx+xo8fnxvryiuv3GP/0qVLszZt2mQRkXXr1i3btm1b5QegkauL+VuwYEHWtm3bLCKyVq1aZbNmzap2nc8991z20Ucflbt/69at2ciRI3O1DB06tNpjNFb5nsN33nkne/XVVyusYfLkyVlRUVEWEVnLli2zFStWlNmuth7Hm5q6WIe7WrNmTW6+evfuXeU6rcOqqUk4cvfdd1c4x1lWe68NG/s6FI40ckuWLMnuvvvu3b46dOiQRUTWoUOHPfatXLlyjz6qEo5kWZb9+te/zrU74ogjsrvuuiubN29e9vjjj2cDBw7M7fva175WYc1f/epXc20HDhyYPf7449m8efOyu+66KzviiCNy+8aNG7e3h6dRWLduXda9e/fcz33ZZZdlzz33XDZnzpzsxz/+cda6devcC4KK0vfqhCOvvfZarv2ZZ55Z5VrvvvvurHnz5tmgQYOyW265JZs6dWr2yiuvZC+//HJ2zz33ZIMHD87127x58+yJJ56oct+NWV3N4c43Vd/+9rezhx56KHvppZeyBQsWZE899VR21VVX5caJiGzEiBEV1mwd7q4u5nDz5s3Zv/7rv+bafP3rX88WLlxY4dfbb7+9Rz8prcNXX301a9myZRYRWevWrbMf//jH2Zw5c7Lnnnsuu+yyy3I/Z/fu3bN169bt8f1VfVH/ne98J9fumGOOye6///5s3rx52f33358dc8wxuX3f/e53y+2jtLQ069+/f67tueeem/3hD3/IXn755ez222/POnbsmEVE1qxZs+ypp56qjcPT4OV7/pYuXZo7rjvDxsrWVFl/DBg5cmTWunXr7Pzzz8/uuOOObMaMGdmCBQuymTNnZr/4xS+yXr165cbo2LFjmeuyqcr3HO7cf/zxx2c//vGPsylTpmTz5s3L5s2blz3wwAPZV77ylaygoCDXxy9/+ctya62tx/Gmpq4eR3f65S9/mWv/85//vMp1Wodlmzlz5m7v5W6++ebccejfv/8e7/XKUpVwJMtq57VhY1+HwpFGbtdf9qp8lXVGR1XDkSzLsjFjxuz2JPXPX6effnq2adOmCvvYuHFjdvrpp5fbR7NmzSpcuE3RkiVLsiOPPLLcY9KmTZts8uTJFfZRnXDkuuuuy7WvzqndVf1969ChQ/bYY49Vud+moC7msKrr/Fvf+la2efPmCseyDveU7znc9bG2ql9lPSantg6feOKJ3BkXZX1179693DNpqvqifvv27dk3v/nNCo/nxRdfnG3fvr3CWletWpX17du33D5atGiR/eY3v9mbw9Ho5HP+qvsaKKLsNwa7/jW6oq/evXtnr732Wi0foYYvn3O46/6Kvvbdd98qhfW18TjeFNXF4+hOX/jCF7KIT8P5sv4oWx7rsGxVPS47v8pS1XCktl4bNuZ1KBxp5Oo6HMmyT6/tPf/887MuXbpkRUVFWceOHbNTTz01+93vflet2idOnJideuqpWceOHbOioqKsS5cu2fnnn1/mKX8p+OSTT7Kbbrop69OnT9a2bdts3333zY466qjsmmuuyZYtW1bp9++cw8rCke3bt2clJSVZxKenxVX2JnpXH3zwQTZ+/PjskksuyY499tispKQka9myZVZcXJx17tw5GzJkSHbbbbdlH3/8cZX7bEryPYdPPPFE9t3vfjc7+eSTsyOOOCLbf//9s8LCwqx9+/ZZnz59smuuuSZbuHBhtWq2DneXzzmsrXAkxXW4bNmy7Jprrsm6d++e7bvvvlnbtm2zPn36ZDfddFO59/fIsuq/qJ8yZUo2bNiwrHPnzllRUVHWuXPnbNiwYdU602Pbtm3Zr371q+yEE07IOnTokBUXF2eHH354dumll2Z//etfq9xPU5Kv+autcGTRokXZrbfemo0YMSL73Oc+lx100EHZPvvsk7Vu3To74ogjsvPOOy/7/e9/v8dp5inJ1xyuW7cuu++++7Irr7wy+8IXvpAdcsgh2b777psVFRVlBx10UHbyySdnN954Y5Uv/82yvX8cb6rq4nF08eLFubannXZateqzDstWl+HITrXx2rCxrsOCLMuyAAAAAEiUj/IFAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACSJhwBAAAAkiYcAQAAAJImHAEAAACS9v8BM6TgXWZ/WagAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 428, + "width": 547 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = balance_base\n", + "for before_mix, rows in df.groupby(df['before_mix']):\n", + " plt.plot(rows['action_mix'], rows['after_profit'])" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "8d86eaa5-af35-4622-b4fe-d739949642d5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Unnamed: 0actionaction_mixpre_vaultpre_pool_0pre_pool_1before_vaultbefore_pool_0before_pool_1after_vaultafter_pool_0after_pool_1pre_mixbefore_mixafter_mixbefore_profitafter_profit
00balance-1.06671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211950.4731770.4731770.47317700
11balance-0.66671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211950.4731770.4731770.47317700
22balance-0.26671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211950.4731770.4731770.47317700
33balance0.26671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211950.4731770.4731770.47317700
44balance0.66671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211950.4731770.4731770.47317700
55balance1.06671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211956671239971682702480515514242934255027827229177158577428585606068211950.4731770.4731770.47317700
66balance-1.06671239971682702480515514242934255027827229177158577428585606068211956671248607084760410201516242934255027827229177136968386622452463696776671257218937234862459318242934255027827229177115489529713243963426490.4731770.542520.6123468635402057929686086118524744522578
77balance-0.66671239971682702480515514242934255027827229177158577428585606068211956671248607084760410201516242934255027827229177136968386622452463696776671257218937234862459318242934255027827229177115489529713243963426490.4731770.542520.6123468635402057929686086118524744522578
88balance-0.26671239971682702480515514242934255027827229177158577428585606068211956671248607084760410201516242934255027827229177136968386622452463696776671257218937234862459318242934255027827229177115489529713243963426490.4731770.542520.6123468635402057929686086118524744522578
99balance0.26671239971682702480515514242934255027827229177158577428585606068211956671248607084760410201516242934255027827229177136968386622452463696776671257218937234862459318242934255027827229177115489529713243963426490.4731770.542520.6123468635402057929686086118524744522578
1010balance0.66671239971682702480515514242934255027827229177158577428585606068211956671248607084760410201516242934255027827229177136968386622452463696776671257218937234862459318242934255027827229177115489529713243963426490.4731770.542520.6123468635402057929686086118524744522578
1111balance1.06671239971682702480515514242934255027827229177158577428585606068211956671248607084760410201516242934255027827229177136968386622452463696776671257218937234862459318242934255027827229177115489529713243963426490.4731770.542520.6123468635402057929686086118524744522578
1212balance-1.066712399716827024805155142429342550278272291771585774285856060682119566712657203301000321325202429342550278272291779418524985019827218314667129074450862356436632624293425502782722917733539562026155358282900.4731770.6824660.886679257486473975516170250241785235322338
1313balance-0.666712399716827024805155142429342550278272291771585774285856060682119566712657203301000321325202429342550278272291779418524985019827218314667129074450862356436632624293425502782722917733539562026155358282900.4731770.6824660.886679257486473975516170250241785235322338
1414balance-0.266712399716827024805155142429342550278272291771585774285856060682119566712657203301000321325202429342550278272291779418524985019827218314667129074450862356436632624293425502782722917733539562026155358282900.4731770.6824660.886679257486473975516170250241785235322338
1515balance0.266712399716827024805155142429342550278272291771585774285856060682119566712657203301000321325202429342550278272291779418524985019827218314667129074450862356436632624293425502782722917733539562026155358282900.4731770.6824660.886679257486473975516170250241785235322338
1616balance0.666712399716827024805155142429342550278272291771585774285856060682119566712657203301000321325202429342550278272291779418524985019827218314667129074450862356436632624293425502782722917733539562026155358282900.4731770.6824660.886679257486473975516170250241785235322338
1717balance1.066712399716827024805155142429342550278272291771585774285856060682119566712657203301000321325202429342550278272291779418524985019827218314667129074450862356436632624293425502782722917733539562026155358282900.4731770.6824660.886679257486473975516170250241785235322338
1818balance-1.06671239971682702480515514242934255027827229177158577428585606068211956671247940752068129565912403127351718788647368178577428585606068211956671255889555273621188510573784870046460961396198577428585606068211950.4731770.4098730.3474627969069365649050479488032054916226
1919balance-0.66671239971682702480515514242934255027827229177158577428585606068211956671247940752068129565912403127351718788647368178577428585606068211956671255889555273621188510573784870046460961396198577428585606068211950.4731770.4098730.3474627969069365649050479488032054916226
2020balance-0.26671239971682702480515514242934255027827229177158577428585606068211956671247940752068129565912403127351718788647368178577428585606068211956671255889555273621188510573784870046460961396198577428585606068211950.4731770.4098730.3474627969069365649050479488032054916226
2121balance0.26671239971682702480515514242934255027827229177158577428585606068211956671247940752068129565912403127351718788647368178577428585606068211956671255889555273621188510573784870046460961396198577428585606068211950.4731770.4098730.3474627969069365649050479488032054916226
2222balance0.66671239971682702480515514242934255027827229177158577428585606068211956671247940752068129565912403127351718788647368178577428585606068211956671255889555273621188510573784870046460961396198577428585606068211950.4731770.4098730.3474627969069365649050479488032054916226
2323balance1.06671239971682702480515514242934255027827229177158577428585606068211956671247940752068129565912403127351718788647368178577428585606068211956671255889555273621188510573784870046460961396198577428585606068211950.4731770.4098730.3474627969069365649050479488032054916226
2424balance-1.066712399716827024805155142429342550278272291771585774285856060682119566712637440111575935083875835965067223143306521857742858560606821195667128696868721455350993542292303059742178292278577428585606068211950.4731770.286070.112812237723284551129928232246760569600016
2525balance-0.666712399716827024805155142429342550278272291771585774285856060682119566712637440111575935083875835965067223143306521857742858560606821195667128696868721455350993542292303059742178292278577428585606068211950.4731770.286070.112812237723284551129928232246760569600016
2626balance-0.266712399716827024805155142429342550278272291771585774285856060682119566712637440111575935083875835965067223143306521857742858560606821195667128696868721455350993542292303059742178292278577428585606068211950.4731770.286070.112812237723284551129928232246760569600016
2727balance0.266712399716827024805155142429342550278272291771585774285856060682119566712637440111575935083875835965067223143306521857742858560606821195667128696868721455350993542292303059742178292278577428585606068211950.4731770.286070.112812237723284551129928232246760569600016
2828balance0.666712399716827024805155142429342550278272291771585774285856060682119566712637440111575935083875835965067223143306521857742858560606821195667128696868721455350993542292303059742178292278577428585606068211950.4731770.286070.112812237723284551129928232246760569600016
2929balance1.066712399716827024805155142429342550278272291771585774285856060682119566712637440111575935083875835965067223143306521857742858560606821195667128696868721455350993542292303059742178292278577428585606068211950.4731770.286070.112812237723284551129928232246760569600016
\n", + "
" + ], + "text/plain": [ + " Unnamed: 0 action action_mix pre_vault \\\n", + "0 0 balance -1.0 66712399716827024805155 \n", + "1 1 balance -0.6 66712399716827024805155 \n", + "2 2 balance -0.2 66712399716827024805155 \n", + "3 3 balance 0.2 66712399716827024805155 \n", + "4 4 balance 0.6 66712399716827024805155 \n", + "5 5 balance 1.0 66712399716827024805155 \n", + "6 6 balance -1.0 66712399716827024805155 \n", + "7 7 balance -0.6 66712399716827024805155 \n", + "8 8 balance -0.2 66712399716827024805155 \n", + "9 9 balance 0.2 66712399716827024805155 \n", + "10 10 balance 0.6 66712399716827024805155 \n", + "11 11 balance 1.0 66712399716827024805155 \n", + "12 12 balance -1.0 66712399716827024805155 \n", + "13 13 balance -0.6 66712399716827024805155 \n", + "14 14 balance -0.2 66712399716827024805155 \n", + "15 15 balance 0.2 66712399716827024805155 \n", + "16 16 balance 0.6 66712399716827024805155 \n", + "17 17 balance 1.0 66712399716827024805155 \n", + "18 18 balance -1.0 66712399716827024805155 \n", + "19 19 balance -0.6 66712399716827024805155 \n", + "20 20 balance -0.2 66712399716827024805155 \n", + "21 21 balance 0.2 66712399716827024805155 \n", + "22 22 balance 0.6 66712399716827024805155 \n", + "23 23 balance 1.0 66712399716827024805155 \n", + "24 24 balance -1.0 66712399716827024805155 \n", + "25 25 balance -0.6 66712399716827024805155 \n", + "26 26 balance -0.2 66712399716827024805155 \n", + "27 27 balance 0.2 66712399716827024805155 \n", + "28 28 balance 0.6 66712399716827024805155 \n", + "29 29 balance 1.0 66712399716827024805155 \n", + "\n", + " pre_pool_0 pre_pool_1 before_vault \\\n", + "0 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "1 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "2 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "3 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "4 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "5 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "6 14242934255027827229177 15857742858560606821195 66712486070847604102015 \n", + "7 14242934255027827229177 15857742858560606821195 66712486070847604102015 \n", + "8 14242934255027827229177 15857742858560606821195 66712486070847604102015 \n", + "9 14242934255027827229177 15857742858560606821195 66712486070847604102015 \n", + "10 14242934255027827229177 15857742858560606821195 66712486070847604102015 \n", + "11 14242934255027827229177 15857742858560606821195 66712486070847604102015 \n", + "12 14242934255027827229177 15857742858560606821195 66712657203301000321325 \n", + "13 14242934255027827229177 15857742858560606821195 66712657203301000321325 \n", + "14 14242934255027827229177 15857742858560606821195 66712657203301000321325 \n", + "15 14242934255027827229177 15857742858560606821195 66712657203301000321325 \n", + "16 14242934255027827229177 15857742858560606821195 66712657203301000321325 \n", + "17 14242934255027827229177 15857742858560606821195 66712657203301000321325 \n", + "18 14242934255027827229177 15857742858560606821195 66712479407520681295659 \n", + "19 14242934255027827229177 15857742858560606821195 66712479407520681295659 \n", + "20 14242934255027827229177 15857742858560606821195 66712479407520681295659 \n", + "21 14242934255027827229177 15857742858560606821195 66712479407520681295659 \n", + "22 14242934255027827229177 15857742858560606821195 66712479407520681295659 \n", + "23 14242934255027827229177 15857742858560606821195 66712479407520681295659 \n", + "24 14242934255027827229177 15857742858560606821195 66712637440111575935083 \n", + "25 14242934255027827229177 15857742858560606821195 66712637440111575935083 \n", + "26 14242934255027827229177 15857742858560606821195 66712637440111575935083 \n", + "27 14242934255027827229177 15857742858560606821195 66712637440111575935083 \n", + "28 14242934255027827229177 15857742858560606821195 66712637440111575935083 \n", + "29 14242934255027827229177 15857742858560606821195 66712637440111575935083 \n", + "\n", + " before_pool_0 before_pool_1 after_vault \\\n", + "0 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "1 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "2 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "3 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "4 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "5 14242934255027827229177 15857742858560606821195 66712399716827024805155 \n", + "6 16242934255027827229177 13696838662245246369677 66712572189372348624593 \n", + "7 16242934255027827229177 13696838662245246369677 66712572189372348624593 \n", + "8 16242934255027827229177 13696838662245246369677 66712572189372348624593 \n", + "9 16242934255027827229177 13696838662245246369677 66712572189372348624593 \n", + "10 16242934255027827229177 13696838662245246369677 66712572189372348624593 \n", + "11 16242934255027827229177 13696838662245246369677 66712572189372348624593 \n", + "12 20242934255027827229177 9418524985019827218314 66712907445086235643663 \n", + "13 20242934255027827229177 9418524985019827218314 66712907445086235643663 \n", + "14 20242934255027827229177 9418524985019827218314 66712907445086235643663 \n", + "15 20242934255027827229177 9418524985019827218314 66712907445086235643663 \n", + "16 20242934255027827229177 9418524985019827218314 66712907445086235643663 \n", + "17 20242934255027827229177 9418524985019827218314 66712907445086235643663 \n", + "18 12403127351718788647368 17857742858560606821195 66712558895552736211885 \n", + "19 12403127351718788647368 17857742858560606821195 66712558895552736211885 \n", + "20 12403127351718788647368 17857742858560606821195 66712558895552736211885 \n", + "21 12403127351718788647368 17857742858560606821195 66712558895552736211885 \n", + "22 12403127351718788647368 17857742858560606821195 66712558895552736211885 \n", + "23 12403127351718788647368 17857742858560606821195 66712558895552736211885 \n", + "24 8758359650672231433065 21857742858560606821195 66712869686872145535099 \n", + "25 8758359650672231433065 21857742858560606821195 66712869686872145535099 \n", + "26 8758359650672231433065 21857742858560606821195 66712869686872145535099 \n", + "27 8758359650672231433065 21857742858560606821195 66712869686872145535099 \n", + "28 8758359650672231433065 21857742858560606821195 66712869686872145535099 \n", + "29 8758359650672231433065 21857742858560606821195 66712869686872145535099 \n", + "\n", + " after_pool_0 after_pool_1 pre_mix before_mix \\\n", + "0 14242934255027827229177 15857742858560606821195 0.473177 0.473177 \n", + "1 14242934255027827229177 15857742858560606821195 0.473177 0.473177 \n", + "2 14242934255027827229177 15857742858560606821195 0.473177 0.473177 \n", + "3 14242934255027827229177 15857742858560606821195 0.473177 0.473177 \n", + "4 14242934255027827229177 15857742858560606821195 0.473177 0.473177 \n", + "5 14242934255027827229177 15857742858560606821195 0.473177 0.473177 \n", + "6 18242934255027827229177 11548952971324396342649 0.473177 0.54252 \n", + "7 18242934255027827229177 11548952971324396342649 0.473177 0.54252 \n", + "8 18242934255027827229177 11548952971324396342649 0.473177 0.54252 \n", + "9 18242934255027827229177 11548952971324396342649 0.473177 0.54252 \n", + "10 18242934255027827229177 11548952971324396342649 0.473177 0.54252 \n", + "11 18242934255027827229177 11548952971324396342649 0.473177 0.54252 \n", + "12 26242934255027827229177 3353956202615535828290 0.473177 0.682466 \n", + "13 26242934255027827229177 3353956202615535828290 0.473177 0.682466 \n", + "14 26242934255027827229177 3353956202615535828290 0.473177 0.682466 \n", + "15 26242934255027827229177 3353956202615535828290 0.473177 0.682466 \n", + "16 26242934255027827229177 3353956202615535828290 0.473177 0.682466 \n", + "17 26242934255027827229177 3353956202615535828290 0.473177 0.682466 \n", + "18 10573784870046460961396 19857742858560606821195 0.473177 0.409873 \n", + "19 10573784870046460961396 19857742858560606821195 0.473177 0.409873 \n", + "20 10573784870046460961396 19857742858560606821195 0.473177 0.409873 \n", + "21 10573784870046460961396 19857742858560606821195 0.473177 0.409873 \n", + "22 10573784870046460961396 19857742858560606821195 0.473177 0.409873 \n", + "23 10573784870046460961396 19857742858560606821195 0.473177 0.409873 \n", + "24 3542292303059742178292 27857742858560606821195 0.473177 0.28607 \n", + "25 3542292303059742178292 27857742858560606821195 0.473177 0.28607 \n", + "26 3542292303059742178292 27857742858560606821195 0.473177 0.28607 \n", + "27 3542292303059742178292 27857742858560606821195 0.473177 0.28607 \n", + "28 3542292303059742178292 27857742858560606821195 0.473177 0.28607 \n", + "29 3542292303059742178292 27857742858560606821195 0.473177 0.28607 \n", + "\n", + " after_mix before_profit after_profit \n", + "0 0.473177 0 0 \n", + "1 0.473177 0 0 \n", + "2 0.473177 0 0 \n", + "3 0.473177 0 0 \n", + "4 0.473177 0 0 \n", + "5 0.473177 0 0 \n", + "6 0.612346 86354020579296860 86118524744522578 \n", + "7 0.612346 86354020579296860 86118524744522578 \n", + "8 0.612346 86354020579296860 86118524744522578 \n", + "9 0.612346 86354020579296860 86118524744522578 \n", + "10 0.612346 86354020579296860 86118524744522578 \n", + "11 0.612346 86354020579296860 86118524744522578 \n", + "12 0.886679 257486473975516170 250241785235322338 \n", + "13 0.886679 257486473975516170 250241785235322338 \n", + "14 0.886679 257486473975516170 250241785235322338 \n", + "15 0.886679 257486473975516170 250241785235322338 \n", + "16 0.886679 257486473975516170 250241785235322338 \n", + "17 0.886679 257486473975516170 250241785235322338 \n", + "18 0.347462 79690693656490504 79488032054916226 \n", + "19 0.347462 79690693656490504 79488032054916226 \n", + "20 0.347462 79690693656490504 79488032054916226 \n", + "21 0.347462 79690693656490504 79488032054916226 \n", + "22 0.347462 79690693656490504 79488032054916226 \n", + "23 0.347462 79690693656490504 79488032054916226 \n", + "24 0.112812 237723284551129928 232246760569600016 \n", + "25 0.112812 237723284551129928 232246760569600016 \n", + "26 0.112812 237723284551129928 232246760569600016 \n", + "27 0.112812 237723284551129928 232246760569600016 \n", + "28 0.112812 237723284551129928 232246760569600016 \n", + "29 0.112812 237723284551129928 232246760569600016 " + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "id": "6b1f355f-75e3-4fac-aa3b-25a422af148f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'Withdraw Profit')" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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hQtNj+uYFlc4cOCA/ZgcPnx4kbYpqWN12rRp9ud+5JFHCjweExNjBAQEGIARFRVl5OTkXPbrczY1l0Quw+bNmw0fHx8DMPz9/Y3XXnvNWLNmjbF06VLjgQcesP+CaNSokZGcnOzquFJJ3XLLLfZjsUePHsa2bduM7du3F/qzZ8+eQvf13HPP2ffVqlUr49tvvzU2bNhgfPvtt0arVq3sjz3//PNOfIUi5xWluWQYOpalbNmzZ48RGBhoAIa3t7fx3HPPGX/88YexYcMG48MPP7Q3lgDjjTfecLgPHdNSVuzatcvw9fW1H3MDBgwwfvzxR2Pz5s3G6tWrjbffftuoW7eu/fGePXs63I+OaSltK1asMKZPn27/efPNN+3HVadOnUyPTZ8+vdD9lMSxmpuba3Tq1Mlee+uttxoLFiww1q1bZ7z//vtGjRo17F9CzJ8/vxT+a5Q8NZdELtMvv/xi7yI7+mnUqJGxb98+V8eUSqywY7Own4iIiEL3lZeXZ4waNeqi2993331GXl6e816gyAWK2lzSsSxlzYoVK4yaNWsWejxaLBbjn//8Z6Hb65iWsuT33383QkJCLvmeo0ePHsapU6cc7kPHtJS24cOHX9Z75MKU1LGamJhotG3bttB9eHl5GZ9++mlJ/2coNRbD+P+TuUWkyA4ePMh7773HvHnzSEhIwNPTk6ioKG6//XYeffRRfH19XR1RKrHLXYMgIiKCuLi4i9bMnz+fKVOmsGHDBk6ePElISAht27ZlzJgx3HDDDVeQVuTKvPTSS7z88stA/ppL3bp1u2i9jmUpS5KSknj//feZPXs2Bw4cIDs7m1q1atGtWzcee+yxS159C3RMS9mRlJTEtGnT+O2339ixYwdnzpzB3d2d0NBQ2rZty5AhQ7j55psv+T5Fx7SUlhEjRvD5558Xuf5SrZKSOFZzc3P59NNP+frrr9m1axdpaWnUrl2bnj17MnbsWK666qoi53U1NZdERERERERERKTYdLU4EREREREREREpNjWXRERERERERESk2NRcEhERERERERGRYlNzSUREREREREREik3NJRERERERERERKTY1l0REREREREREpNjUXBIRERERERERkWJTc0lERERERERERIpNzSURERERERERESk2NZdERERERERERKTY1FwSEREREREREZFiU3NJRERERERERESKTc0lEREREREREREpNjWXRERERERERESk2NRcEhERERERERGRYlNzSUREREREREREik3NJREREREpssjISCwWCyNGjHB1FIeWLVuGxWLBYrGwbNkyV8cRERGpFNRcEhEREXGCC5sef//x9fUlIiKCQYMG8fXXX5Obm+vquKUmLi7O9NqtVisHDx4s0raNGjUybTtjxozSDSsiIiJFouaSiIiIiItlZGRw6NAh5syZw9ChQ7nuuus4duyYq2M5hWEYzJw585J1a9euZd++fU5IJCIiIpdLzSURERERJ3vooYfYvn27/WfNmjW8//77REZGArBhwwYGDhyIYRiuDVrKvL29Afjyyy8vWXuu5tw2henWrRuGYWAYBt26dbvijCIiInJpai6JiIiIOFmNGjW4+uqr7T8dOnTg0UcfZfPmzURFRQGwfv16fv31VxcnLV0333wzALt372bjxo2F1uXk5PDdd98BMHDgQKdkExERkaJTc0lERESkjAgKCuL555+331+wYIEL05S+pk2b0qZNG+Dis5fmz59PUlISnp6e3Hnnnc6KJyIiIkWk5pKIiIhIGdKuXTv7bUcLXScmJvLPf/6TVq1aERgYiLe3N5GRkdx7772sXLmySM8RFxfHk08+yVVXXUWVKlXw9fWlYcOGjBkzhu3bt5fYaymKe++9F4Bvv/220IXMv/jiCwBuuukmgoKCLrq/i10t7rXXXrM/NnHixEL3sWnTJjw9PbFYLHTv3h2bzXYZr0hERKTyUXNJREREpAzx8PCw387LyzM9tmjRIqKionj11VfZunUrZ8+eJSsri4MHD/LVV1/RpUsXHn300Ys2Q7744guaNGnCu+++y86dO0lNTSUjI4OYmBimTJlCq1ateP3110vt9f3dXXfdhbu7OydOnGDhwoUFHj99+jTz5s0Dzjeiiuu5556jS5cuAPzrX/9i69atBWrS09MZOnQoOTk5BAYG8sUXX2C16i2ziIjIxegvpYiIiEgZcuHModq1a9tvb926lQEDBpCcnIyHhwdPPvkk0dHRrF+/nk8++YR69eoB8OGHH5pOrbvQvHnzGDFiBFlZWfj7+zNhwgRWrFjBmjVreOuttwgJCSEvL49//OMf/O9//yvdF/r/atSoQd++fQHHp8Z9//33ZGVlUa1aNfr3739Fz2W1Wvnyyy+pWrUq2dnZDBkyhIyMDFPNU089xZ49ewD43//+R3h4+BU9p4iISGWg5pKIiIhIGZGbm8tbb71lv3/h1c4eeOABsrOzcXNz49dff+Xtt9+mW7dutG3blgceeIBNmzbRrFkzACZNmsSOHTtM+87JyeGBBx7AMAz8/f1ZsWIFL730Ep07d6ZDhw489dRTbNy4kVq1agHwzDPPcPLkydJ/0cCwYcMA+OWXX0hOTjY9dq7hdOedd+Lp6XnFzxUREcGHH34IwK5duxg3bpz9sblz5/LJJ58AMHToUO66664rfj4REZHKQM0lERERERdLS0tj+fLl9O7dm7Vr1wL5TZA77rgDyL9y3IYNGwC4//776dOnT4F9BAUFMWXKFABsNhsfffSR6fFZs2Zx5MgRAP75z3/SsmXLAvuIiIjgzTffBPJPD5s+fXrJvMBLuPnmm6latSoZGRn89NNP9vH9+/ezatUq4MpPibvQ0KFDufvuu4H8mV6//fYbx48f57777gPMDSgRERG5NDWXRERERJzs5Zdfti8sbbFY8Pf3p1u3bvYFqGvUqMHs2bPx8vICYPHixfZtzzVAHOnUqRNNmzYtsM2F9y0WC6NGjSp0H7fffjtVq1Z1uI/S4u3tzW233QaYT4376quvAGjYsCEdOnQo0ef86KOPqFu3LgAjR45kyJAhJCYmmk6dExERkaJRc0lERESkjKhXrx7jxo1j+/btpplFf/31FwCenp4OZxxdqH379gDs27eP7OzsAvuoV68e1atXL3R7T09PWrVqZdrGGc6dGrds2TLi4+OB842mkpy1dM6Fi3UfP36cpUuXAvDss8/aF/0WERGRonF3dQARERGRyuahhx7i4YcfBvJnEnl7exMSElLobJlTp04BEBwcjLv7xd++hYaGAmAYBqdPn6ZmzZqmfdSoUeOS+c7t49w2ztClSxciIiI4ePAgM2fOpGvXrsTExGCxWLjnnntK5Tm7du3Kvffey+effw5As2bNePnll0vluURERCoyNZdEREREnKxGjRpcffXVl72dxWK54ucuiX2UhnNNpFdffZUvv/ySQ4cOAfmn+p27El5Ji4+PZ86cOfb7Bw4cICYmxn5qoYiIiBSNTosTERERKeOCg4MBSEpKIjc396K1x44dA/KbNUFBQQX2cfz48Us+37l9nNvGWc6dGrdz5077YuLnxkqazWZj2LBhnDlzBg8PD3x8fMjIyGDo0KHk5OSUynOKiIhUVGouiYiIiJRx52Y5ZWdns3Xr1ovWrl+/HshfBNvT07PAPg4cOEBiYmKh2+fk5LBlyxbTNs7SqFEj2rVrB0BmZiZeXl7cfvvtpfJckyZNsi+gPmHCBCZOnAjAli1b+Ne//lUqzykiIlJRqbkkIiIiUsb16tXLfvuzzz4rtG7NmjXs3LmzwDYX3jcMwz4ryJEff/yRs2fPOtyHMwwfPhwvLy+8vLwYPHgwgYGBJf4cW7dutTeQOnfuzHPPPcejjz7KDTfcAMCbb77JihUrSvx5RUREKio1l0RERETKuHbt2tGmTRsAPv30U5YsWVKg5uzZs4wZMwYAq9XKQw89ZHp80KBB1K5dG4BXX32V7du3F9hHfHw8zzzzDAC+vr6MHDmyRF9HUTz88MNkZmaSmZnJN998U+L7z8zMZOjQoWRnZxMQEMCXX36Jm5sbkN+4CwkJwWazce+995KcnFzizy8iIlIRqbkkIiIiUg58+umneHp6kpubS//+/XnmmWdYvnw5Gzdu5NNPP+Xaa6+1N4yeeeaZAqe0eXp6MmXKFCwWC8nJyXTq1IlXXnmF1atXs27dOt555x3atGnDkSNHgPzTxkJCQpz+Okvb+PHj7bO73n//fSIjI+2PhYaGMnXqVAAOHjzIo48+6oqIIiIi5Y6aSyIiIiLlQMuWLZk7dy4BAQFkZ2fz1ltv0a1bN9q2bcsDDzzA/v37AXjkkUd4/fXXHe7jxhtvZPr06Xh5eZGSksKLL75Ip06d6NChA0899RQnTpzAzc2N1157rcDMp4pg0aJFfPDBBwDcfvvtDhcLHzhwIKNHjwbgyy+/5IcffnBqRhERkfJIzSURERGRcqJPnz7ExMTwj3/8g5YtWxIQEICXlxd169Zl6NChrFixgg8++ACrtfC3eMOHD2f37t2MHTuWpk2b4ufnh4+PDw0aNOD+++9ny5YtPP/88058Vc6RlJTEiBEjMAyDOnXq8MknnxRa++6779KwYUMAxowZw+HDh50VU0REpFyyGIZhuDqEiIiIiIiIiIiUT5q5JCIiIiIiIiIixabmkoiIiIiIiIiIFJuaSyIiIiIiIiIiUmxqLomIiIiIiIiISLGpuSQiIiIiIiIiIsWm5pKIiIiIiIiIiBSbmksiIiIiIiIiIlJsai6JiIiIiIiIiEixqbkkIiIiIiIiIiLFpuaSiIiIiIiIiIgUm5pLIiIiIiIiIiJSbGouiYiIiIiIiIhIsam5JCIiIiIiIiIixabmkoiIiIiIiIiIFJuaSyIiIiIiIiIiUmxqLomIiIiIiIiISLGpuSQiIiIiIiIiIsWm5pKIiIiIiIiIiBSbmksiIiIiIiIiIlJsai6JiIiIiIiIiEixqbkkIiIiIiIiIiLFpuaSiIiIiIiIiIgUm5pLIiIiIiIiIiJSbGouiYiIiIiIiIhIsam5JCIiIiIiIiIixfZ/lirIT0CopzAAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 454, + "width": 587 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = withdraw_base\n", + "df = df[df.before_mix != df.after_mix]\n", + "\n", + "plt.title(\"Withdraw profit\")\n", + "plt.axhline(0, c=\"black\", linewidth=0.4)\n", + "for before_mix, rows in df.groupby(df['before_mix']):\n", + " plt.plot(rows['action_mix']*100, rows['after_profit'])\n", + "plt.ylim([-1e18,1e18])\n", + "plt.xlabel(\"Pool Mix\")\n", + "plt.ylabel(\"Withdraw Profit\")" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "id": "2dc420a4-af9d-4907-9a16-2de4ab697696", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.03596896224969377" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Unnamed: 0actionaction_mixpre_vaultpre_pool_0pre_pool_1before_vaultbefore_pool_0before_pool_1after_vaultafter_pool_0after_pool_1pre_mixbefore_mixafter_mixbefore_profitafter_profit
00withdrawall-2.06671239971682702480515514242934255027827229177158577428585606068211956671257195391392567096118242934255027827229177115489506296853600952236671474601088157466110216420102681620710042601103954368799876203368040.4731770.6123460.6123351722370869008658062174056967648990141
11withdrawall-1.26671239971682702480515514242934255027827229177158577428585606068211956671250328754594621483216642934255027827229177132661364210707253976526671317744233594599292614980199351751540141657119411094763942849355560.4731770.5564510.556444103570718921409677674154789999778094
22withdrawall-0.46671239971682702480515514242934255027827229177158577428585606068211956671243431231735416784315042934255027826929177149919466025584354877596671247028127960386162013540296021882369970943134945450554140077526860.4731770.5008490.5008463459549032936268835968962249693777
33withdrawall0.46671239971682702480515514242934255027827229177158577428585606068211956671243163895027085134313505867050482667428761166577428585606065211956671254479949405071843712156895715868359306935149938169043890172561140.4731770.4477540.44775631922123246046188113160543779867094
44withdrawall1.26671239971682702480515514242934255027827229177158577428585606068211956671249529921512251164712036352111368635374694182577428585606073211956671332327174330197453810834156509200284929828164337202342581878766480.4731770.3973170.39732395582388097706492827972528179462891
55withdrawall2.0667123997168270248051551424293425502782722917715857742858560606821195667125586929230737419311057378301021330987530219857742858560606821195667148532679742539151399517669387452615412383178736235641273573279240.4731770.3474610.3474711589760960489367762294575051180173208
\n", + "
" + ], + "text/plain": [ + " Unnamed: 0 action action_mix pre_vault \\\n", + "0 0 withdrawall -2.0 66712399716827024805155 \n", + "1 1 withdrawall -1.2 66712399716827024805155 \n", + "2 2 withdrawall -0.4 66712399716827024805155 \n", + "3 3 withdrawall 0.4 66712399716827024805155 \n", + "4 4 withdrawall 1.2 66712399716827024805155 \n", + "5 5 withdrawall 2.0 66712399716827024805155 \n", + "\n", + " pre_pool_0 pre_pool_1 before_vault \\\n", + "0 14242934255027827229177 15857742858560606821195 66712571953913925670961 \n", + "1 14242934255027827229177 15857742858560606821195 66712503287545946214832 \n", + "2 14242934255027827229177 15857742858560606821195 66712434312317354167843 \n", + "3 14242934255027827229177 15857742858560606821195 66712431638950270851343 \n", + "4 14242934255027827229177 15857742858560606821195 66712495299215122511647 \n", + "5 14242934255027827229177 15857742858560606821195 66712558692923073741931 \n", + "\n", + " before_pool_0 before_pool_1 after_vault \\\n", + "0 18242934255027827229177 11548950629685360095223 66714746010881574661102 \n", + "1 16642934255027827229177 13266136421070725397652 66713177442335945992926 \n", + "2 15042934255027826929177 14991946602558435487759 66712470281279603861620 \n", + "3 13505867050482667428761 16657742858560606521195 66712544799494050718437 \n", + "4 12036352111368635374694 18257742858560607321195 66713323271743301974538 \n", + "5 10573783010213309875302 19857742858560606821195 66714853267974253915139 \n", + "\n", + " after_pool_0 after_pool_1 pre_mix before_mix \\\n", + "0 16420102681620710042601 10395436879987620336804 0.473177 0.612346 \n", + "1 14980199351751540141657 11941109476394284935556 0.473177 0.556451 \n", + "2 13540296021882369970943 13494545055414007752686 0.473177 0.500849 \n", + "3 12156895715868359306935 14993816904389017256114 0.473177 0.447754 \n", + "4 10834156509200284929828 16433720234258187876648 0.473177 0.397317 \n", + "5 9517669387452615412383 17873623564127357327924 0.473177 0.347461 \n", + "\n", + " after_mix before_profit after_profit \n", + "0 0.612335 172237086900865806 2174056967648990141 \n", + "1 0.556444 103570718921409677 674154789999778094 \n", + "2 0.500846 34595490329362688 35968962249693777 \n", + "3 0.447756 31922123246046188 113160543779867094 \n", + "4 0.397323 95582388097706492 827972528179462891 \n", + "5 0.347471 158976096048936776 2294575051180173208 " + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABG4AAAOACAYAAABrJDUWAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/OQEPoAAAACXBIWXMAAB7CAAAewgFu0HU+AADOqUlEQVR4nOzdeXxU9b3/8ffJZA+BBEISyMqOCLIm7KCoqFVEFDC4grX2qt1trz97b9Uu3tvFa7W2trUqICpRFDfcRUEMS8K+yxqSkJ0lJGTPzO8P6sAJhCXMzJnl9Xw88mjOJ+fMeWshZj75ns/XcDgcDgEAAAAAAMDrBFkdAAAAAAAAAGdG4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNmwBVXl6uJUuW6NFHH9V1112nuLg4GYYhwzA0e/Zsj+Ww2+3avn275s2bpwceeEAZGRkKCwtzZlm2bNkFvd7HH3+srKws9ezZU5GRkQoPD1dKSoqmTp2q119/XXa73T3/IAAAAAAAuEGw1QFgjYSEBKsjSJIWLFjgkkZRQ0ODbr/9dr311lunfa2oqEhFRUV677339Le//U3vvfeeYmJiLvqeAAAAAAC4GytuoNTUVE2ePNmSezscDufnISEhGjZsmAYNGnTBr/OjH/3I2bSJj4/Xk08+qS+++EIrVqzQc889p7S0NEnSihUrlJWV5ZrwAAAAAAC4GStuAtSjjz6qjIwMZWRkKCEhQfn5+erRo4fHcwwYMEB/+ctflJGRoSFDhig8PFyPP/64tmzZct6vUVZWphdeeEGSFBsbq3Xr1ik5Odn59XHjxun222/X4MGDlZ+fr08++URr167ViBEjXP7PAwAAAACAK9G4CVC//vWvrY4gScrMzFRmZuZFvcaaNWucs2vmzJljatp8q2PHjvrpT3+qH//4x5KkVatW0bgBAAAAAHg9HpXCRauvr9df//pXXXnllUpMTFRoaKji4+N11VVX6cUXX1Rzc7Nb79/Y2Oj8vGfPnm2e16tXrzNeAwAAAACAt2LFDS7Kpk2bNHXqVB04cMBUr6io0NKlS7V06VL985//1Pvvv++2gcj9+vVzfr5v3742z9u7d+8ZrwEAAAAAwFux4gbttmfPHk2cOFEHDhxQx44d9cgjj+jtt9/W2rVr9cknn+jBBx9UcHCw8vLyNHXqVDU1Nbklx6BBgzRmzBhJ0rx581RcXHzaOdXV1Xr66aclnViVY9UwZgAAAAAALgQrbtBud999t6qqqjR06FB9+umniouLM3198uTJuuGGG3T99ddrzZo1mjdvnr73ve+5JcvcuXN17bXXav/+/Ro2bJj+8z//U8OGDVNwcLC2bt2qP/7xj9q/f7/i4uL06quvKjQ01C05AAAAAABwJVbcoF1WrFihlStXSpLmz59/WtPmW9dee62mT58u6cRqGHfp27ev8vLy9Nvf/lbHjx/XQw89pCuuuELjx4/X/fffr6KiIv385z/Xhg0bNGrUKLflAAAAAADAlWjcoF3ee+89SSdmxQwaNOis506YMEGSlJeX59ZBxe+//75effVV1dTUnPa1pqYmvfHGG3rttdfkcDjclgEAAAAAAFeicYN2Wbt2rSTpm2++kWEYZ/34wQ9+IOlE8+Tw4cNuyfPQQw9pzpw52rlzp2666Sbl5OSopqZGdXV1Wr9+vebMmaOCggI9/PDDmj59ulpaWtySAwAAAAAAV6Jxg3YpLy9v13W1tbUuTiJ98MEHeuqppyRJs2fP1ttvv60xY8YoKipK4eHhGjp0qF566SX96le/kiQtXrxYzz33nMtzAAAAAADgagwnRrt8u2Jl8ODBeuWVV877uqSkJJdneeGFFyRJhmHod7/7XZvn/fKXv9Sf//xn1dTU6KWXXtIPf/hDl2cBAAAAAMCVaNygXbp06SJJqqmp0cCBAy3NsmPHDklSfHz8WRtD4eHhuvTSS7VmzRrt3LnTU/EAAAAAAGg3HpVCuwwdOlSStG/fPpWWllqaJTj4RP/xfAYfNzU1ma4BAAAAAMCb0bhBu9x4442SJIfDoWeeecbSLD169JAkHTp0yLn65kwOHz6srVu3mq4BAAAAAMCb0bhBu0yePFmZmZmSpD/96U964403znr+li1b9P7777sly5QpU5yf/+QnP1FjY+Np59jtdv3oRz9yfu2GG25wSxYAAAAAAFzJcDgcDqtDwPO+/vpr7dmzx3lcWVmpX/ziF5KksWPH6t577zWdP3v27NNeY+/evcrMzHRu8T1lyhTdeuut6tOnj2w2m8rLy7Vhwwa9//77Wr16tR566CE9+eSTp73OvHnzTMfvvPOO3n33XUnSww8/rP79+zu/1rt3b40bN850fmNjo4YMGeJcbTNo0CD98Ic/1ODBg2Wz2bR9+3b9/e9/16pVqyRJCQkJ2rp1q+Li4s7nXxUAAAAAAJahcROgZs+erfnz55/3+W39Mdm1a5duueUW5yNIZ/PrX/9ajz766Gl1wzDOO8fdd999WqNHkg4cOKCpU6dq06ZNZ72+R48eWrx4sYYMGXLe9wQAAAAAwCpMaMVF6du3rzZu3Kg33nhDb731lvLy8lRRUaGWlhZ16dJF/fr107hx4zRt2jQNGzbMbTnS0tKUl5en7Oxsvfnmm1q/fr0qKirkcDjUuXNnXXbZZbrpppt01113KSoqym05AAAAAABwJVbcAAAAAAAAeCmGEwMAAAAAAHgpGjcAAAAAAABeisYNAAAAAACAl6JxAwAAAAAA4KVo3AAAAAAAAHgptgMPAPX19dqyZYskqWvXrgoO5v92AAAAAABcrbm5WRUVFZKkQYMGKTw8/KJfk3fwAWDLli3KzMy0OgYAAAAAAAEjNzdXGRkZF/06PCoFAAAAAADgpVhxEwC6du3q/Dw3N1fdunWzMA0AAAAAAP6ppKTE+cTLqe/FLwaNmwBw6kybbt26KTk52cI0AAAAAAD4P1fNl+VRKQAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNGwAAAAAAAC9F4wYAAAAAAMBL0bgBAAAAAADwUjRuAAAAAAAAvBSNG3itrQer9F9vb9Fn28usjgIAAAAAgCWCrQ4AtLZ0R5n+/PkubT14TJJUcLhWVw9IsDgVAAAAAACex4obeJ1j9U3Opo0krdhdqYJDtRYmAgAAAADAGjRu4HWuG9hNHcPNi8FeX1tgURoAAAAAAKxD4wZeJzzEppuHJZtqi9YWqbnFblEiAAAAAACsQeMGXikrM8V0XF7doC92lluUBgAAAAAAa9C4gVfqn9hRQ1NjTLXsvEJrwgAAAAAAYBEaN/BaszJSTcfLvilX8dE6i9IAAAAAAOB5NG7gtW4Y3E0dwk4OKbY7pDfWsuoGAAAAABA4aNzAa0WGBuvGId1NtTfyCtVid1iUCAAAAAAAz6JxA6/W+nGp4qp6fbW7wqI0AAAAAAB4Fo0beLVByZ10afeOplp2boFFaQAAAAAA8CwaN/B6szLNq26W7ihXeXW9RWkAAAAAAPAcGjfwelOHdFdEiM153Gx36M11RRYmAgAAAADAM2jcwOtFh4fohsu6mWrZuYWyM6QYAAAAAODnaNzAJ2S1elyq4HCtVu07ZFEaAAAAAAA8g8YNfMKw1Bj1Tehgqi1kSDEAAAAAwM/RuIFPMAxDWa22Bv90W5kOH2+0KBEAAAAAAO5H4wY+4+ZhSQoNPvlHtrHFrsXrGVIMAAAAAPBfNG7gM2IiQ/WdgYmm2sLcAjkcDCkGAAAAAPgnGjfwKa2HFO+tOK68/CMWpQEAAAAAwL1o3MCnjOzRWT3joky1bIYUAwAAAAD8FI0b+BTDMHRrRoqp9sGWElXVNlmUCAAAAAAA96FxA59zy/BkhdgM53FDs13vbDxoYSIAAAAAANyDxg18TlyHME0ewJBiAAAAAID/o3EDn5SVaX5camdptTYVVVmUBgAAAAAA96BxA580tlecUjpHmGoL1zCkGAAAAADgX2jcwCcFBRm6dYR51c37m4tV09BsUSIAAAAAAFyPxg181owRKbIFnRxSXNvYovc2FluYCAAAAAAA16JxA5+V0DFcV/SLN9Wy83hcCgAAAADgP2jcwKfdNtL8uNTmoiptK2ZIMQAAAADAP9C4gU+b2Dde3TqFm2rZuYUWpQEAAAAAwLVo3MCn2YIMzWg1pPidDQdV28iQYgAAAACA76NxA583c0SyjJMzilXd0KwPNpdYFwgAAAAAABehcQOflxwbqQl9uppq2Xk8LgUAAAAA8H00buAXZmWaH5dad+CIdpVVW5QGAAAAAHCxNhQc0ZfflMtud1gdxVI0buAXrrwkQXEdwkw1hhQDAAAAgO966rNdmjM3T1f9ebkWrMrX8YbAnGVK4wZ+IcQWpBkjkk21xRuKVN/UYlEiAAAAAEB77Smv1ordlZKkfRXH9at3twXsLFMaN/AbWRnmx6WO1jbpk22lFqUBAAAAALTX3Jx803FsZIhuHNLdmjAWo3EDv5HWJUpjenUx1RbmFliUBgAAAADQHlW1TVq8/qCpdtvIVIWH2CxKZC0aN/ArWZmppuPV+w5rf+Vxi9IAAAAAAC5Udl6B6k4ZexEcZOjOUenWBbIYjRv4lWsuTVBsZIiplp3HqhsAAAAA8AXNLXa9vOqAqXbdoG5K7BRuUSLr0biBXwkLtumWYeYhxW+tK1Jjs92iRAAAAACA8/XZ9jIdPFpnqs0Zm25NGC9B4wZ+JyvTPKS4sqZRS3eUWZQGAAAAAHC+5q7MNx0PTonRsNRYa8J4CRo38Du946OVkW7+i/0aQ4oBAAAAwKttK65S7v7Dpto9Ab7aRqJxAz+VlWEeUvz1nkoVHq61KA0AAAAA4FxabwEeHx2m6wZ2syaMF6FxA7/0nUHdFB0e7Dx2OKQ31hZamAgAAAAA0JbKmga9t7HYVLtzVJpCg2lb8G8Afiki1KZpQ5NMtTfWFqq5hSHFAAAAAOBtXltToMZT3q+F2oI0a2TqWa4IHDRu4LdaPy5VdqxBy76psCgNAAAAAOBMGpvtWrDavAX4jUO6K65DmEWJvAuNG/itAd07anBKjKmWnceQYgAAAADwJh9uKVFFdYOpFuhbgJ+Kxg382qwM89bgX+wsV0lVnUVpAAAAAACncjgcmpuz31TL7NFZl3bvZFEi70PjBn5tyuDuigq1OY/tDmnR2iILEwEAAAAAvrW+4Kg2FVWZamwBbkbjBn4tKixYNw7pbqq9nlcou91hUSIAAAAAwLdar7ZJionQ1QMSLUrjnWjcwO+1HlJ88GidVuyptCgNAAAAAECSSqrq9NHWUlPt7jFpsgUZFiXyTjRu4PcuS+6kAd06mmrZuQwpBgAAAAArvbL6gFpOeRoiIsSmW0ewBXhrNG7g9wzD0KxM85Diz7aXnTa1HAAAAADgGfVNLXptjfkX6rcMT1KnyBCLEnkvGjcICFOHJik85OQf92a7Q2+uY0gxAAAAAFjh3Y0HdaS2yVSbPSbdmjBejsYNAkLH8BBdP6j1kOICORwMKQYAAAAATzqxBXi+qTa+T5x6x0dbE8jL0bhBwGj9uFT+oVqt2nfIojQAAAAAEJhW7TuknaXVpto9Y3tYlMb70bhBwBieFqve8R1MtezcQovSAAAAAEBgar3apmdclCb27WpNGB9A4wYB48SQYvOE8o+3lurI8UaLEgEAAABAYCk4VKvPd5SZanePSVcQW4C3icYNAsrNQ5MUajv5x76xxa7FGw5amAgAAAAAAsf8Vfk6ddRodFiwbhmebF0gH0DjBgElNipU1w5MNNUW5jKkGAAAAADcraahWW/kmcdVzMxIUYewYIsS+QYaNwg4Wa2GFO8pr9G6A0csSgMAAAAAgeGtdUWqbmh2HhuGdPfodOsC+QgaNwg4o3t2UXqXSFNtIUOKAQAAAMBt7HaH5q/MN9WuuiRBqa3em+F0NG4QcAzD0K0Z5iHFH2wpVlVdk0WJAAAAAMC/Ld9doX2Vx021OWPTrQnjY2jcICBNH56s4FOmltc32fXeRoYUAwAAAIA7tN4CvH9itEb37GJNGB9D4wYBqWt0mK4ekGCqvZZbyJBiAAAAAHCxPeU1+mpXhak2e0y6DIMtwM8HjRsErKxM8+NSO0qOaXNRlUVpAAAAAMA/zVu533QcGxmim4YmWZTG99C4QcAa3ztOSTERplp2XoFFaQAAAADA/1TVNumtdeaxFLMyUxUeYrMoke+hcYOAFRRk6NYM89bg720s1vFTtqcDAAAAALTf62sLVNfU4jy2BRm6c3SahYl8D40bBLQZI5J1yoxiHW9s0fubiq0LBAAAAAB+ornFrvkrD5hq1w1MVLdOEW1cgTOhcYOA1q1ThCb1jzfVFuYVWpQGAAAAAPzH5zvKdPBonak2Z2wPi9L4Lho3CHhZGeYhxZsKj2p78TGL0gAAAACAf3ip1Rbgg5M7aVhqjCVZfBmNGwS8y/t1VULHMFONIcUAAAAA0H7biquUu/+wqTZnbA+2AG8HGjcIeMG2IM0cYR5S/PaGg6prbGnjCgAAAADA2cxrtdomPjpM3xnUzZowPo7GDSBp5ogUndr4ra5v1odbSqwLBAAAAAA+6lBNg95ttenLHaPSFBpMC6I9+LcGSErpHKlxveNMNR6XAgAAAIAL99qaAjU2253HobYg3TYy9SxX4Gxo3AD/dlum+RtJXv4R7SmvtigNAAAAAPiexma7Fqw2bwE+ZXB3xXUIa+MKnEvANm7Wrl2r3/zmN5o8ebKSk5MVFhamDh06qG/fvpozZ46+/vprl99z4cKFmjx5shITExUeHq60tDTdcccdWrVqlcvvhQt35SUJiusQaqpl57I1OAAAAACcr4+2lqi8usFUmzM23ZowfsJwOBwOq0N42oQJE7RixYpznnfXXXfpX//6l0JDQ8957tnU1dVp+vTp+vDDD8/49aCgID366KN67LHHLuo+bSkqKlJKyonhu4WFhUpOTnbLffzB/360Q/9cvs95HBsZotW/vFJhwTYLUwEAAACAb5j6txxtKjzqPM5M76w3/mO0dYE8zB3vvwNyxU1x8YkhSd27d9ePf/xjvfnmm8rNzdWqVav01FNPKSkpSZL08ssva/bs2Rd9v3vuucfZtLniiiv0zjvvKDc3Vy+++KJ69eolu92uxx9/XM8///xF3wsXJyvD/LjUkdomfbKtzKI0AAAAAOA71hccMTVtJFbbuEJArri54YYbdNddd+mWW26RzXb6SorKykqNHTtWu3btkiQtX75cEyZMaNe9vvjiC1155ZWSpClTpujtt9823bOyslLDhw9XQUGBYmJitG/fPsXGxrbrXm1hxc2FyXp+lVbvO+w8HtOri1773igLEwEAAACA9/vhwg16/5TdpJJiIrT8F5cr2BY4a0ZYceMiS5Ys0cyZM8/YtJGkuLg4/d///Z/z+M0332z3vZ588klJUnBwsJ577rnT7hkXF6c//OEPkqSjR4/qhRdeaPe94BqzWg0pXrn3kA4cOm5RGgAAAADwfqVV9fpoS4mpdtfotIBq2rgL/wbbcMUVVzg/37t3b7teo7q6WkuXLpUkXXXVVW122m6++WZ17NhRkvT222+3615wnWsuTVRMZIiplp3HkGIAAAAAaMuC1flqtp98oCcixHbaKAq0D42bNjQ0nJyC3dbKnHPJy8tTY2OjJGnixIltnhcaGqpRo0Y5r2lqamrX/eAa4SE23TzU3GRbtLZITS12ixIBAAAAgPeqb2rRa2sKTLWbhyWpU6tfiKN9aNy0Yfny5c7PL7nkkna9xvbt252f9+/f/6znfvv15uZm7d69u133g+vMykwxHVfWNGjpDoYUAwAAAEBr720s1pFa8wIEhhK7TrDVAbyR3W7X73//e+fxzJkz2/U6RUVFzs/PNZDo2+FF0okBRgMGDGjXfc6kpKTkrF/H6fokRGt4WqzWHTjirC3MLdS1A7tZmAoAAAAAvIvD4dBLOftNtfF94tQ7PtqiRP6Hxs0Z/PnPf1Zubq6kE/Nnhg8f3q7Xqa6udn7eoUOHs54bFRXl/LympuaC7nNq0weuk5WRYmrcfLW7QkVHapUcG2lhKgAAAADwHqv3HdbO0mpTjdU2rsWjUq0sX75c/+///T9JUnx8vP7+97+3+7Xq6+udn4eGhp713LCwMOfndXV17b4nXOf6y7opOuxkb9PhkN5Ye/bVTQAAAAAQSOa2Wm3TIy5Kl/eNtyiNf2LFzSm2bdumadOmqbm5WeHh4Vq0aJHi49v/By48PNz5+bdDitty6jDkiIiIC7pPYeHZdzwqKSlRZmbmBb0mpMjQYN00NEkLVh9w1hatLdSPr+wjW5BhYTIAAAAAsF7h4Vp91moW6N2j0xTE+yWXonHzb/v379fkyZN15MgR2Ww2ZWdna8KECRf1mtHRJ5/pO9fjT8ePH3d+fq7Hqlo71/wctF9WZoqpcVNSVa/lu8o1qX+ChakAAAAAwHrzV+bLcXIHcEWHBWv6CEZ5uBqPSkkqLi7WVVddpeLiYhmGoZdeeklTp0696Nc9taFyrgHCp66aYWaN97i0eyddltzJVHttzdlXOAEAAACAvzve0KzX15rfG80YkaIOYawPcbWAb9xUVlbq6quv1r59+yRJzz77rO666y6XvPapO0Pt3LnzrOd++/Xg4GD16dPHJfeHa2RlpJqOv/ymXGXH6ts4GwAAAAD831vri1Rd3+w8Ngxp9ph06wL5sYBu3FRVVemaa67R9u3bJUm///3v9eCDD7rs9TMyMpxDiZcvX97meY2NjVq9erXzmpCQEJdlwMW7cUh3RYbanMctdocWrWXVDQAAAIDAZLc7NC8n31S7sn+CUruwA687BGzjpra2Vtdff73Wr18vSfqv//ovPfzwwy69R3R0tK688kpJ0ueff97m41KLFy/WsWPHJEnTpk1zaQZcvA5hwZpyWXdT7fW1hbLbHW1cAQAAAAD+66vdFdpXedxUu4ctwN0mIBs3jY2NmjZtmnJyciRJP/7xj/W73/3ugl9n3rx5MgxDhmHo8ccfP+M5P//5zyVJzc3NevDBB9XS0mL6emVlpbNhFBMTo3vvvfeCc8D9Zo00Py5VeLhOOXsrLUoDAAAAANaZ22q1Tb+EaI3u1cWaMAEgIKcGzZo1S59++qkkadKkSfrud7+rrVu3tnl+aGio+vbt2657TZo0SVlZWcrOztZ7772nq6++Wj/5yU/UvXt3bdmyRU888YQKCgokSX/4wx8UGxvbrvvAvQYnd1L/xGjtLK121rJzCzW+T1cLUwEAAACAZ+0pr9HyXRWm2pyx6TIMtgB3l4Bs3CxevNj5+RdffKHLLrvsrOenpaUpPz+/3fd76aWXdOzYMX344Yf68ssv9eWXX5q+HhQUpF/96le677772n0PuJdhGJqVmarH3tvmrH26vVSVNQ2K6xBmYTIAAAAA8Jz5K/NNxzGRIZo6JMmaMAEiIB+V8rSIiAh98MEHevXVV3X11VcrPj5eoaGhSklJ0W233aavv/66zUet4D1uGpKksOCTf2WaWhx6a93Zt3kHAAAAAH9RVdekt9ab3wPNykxVxCmbucD1DIfDwYRVP1dUVKSUlBRJUmFhoZKTky1O5Lt+9vpGLd5w0HncMy5KSx+ayLJAAAAAAH7vX1/t0xMf7nAe24IMrfjPK9Q9JsLCVN7FHe+/WXEDXICsTPOQ4n2Vx7Vm/2GL0gAAAACAZ7TYHZq/Kt9Uu3ZgIk0bD6BxA1yAjPRY9eoaZapl5xZYlAYAAAAAPOOz7WUqOlJnqrEFuGfQuAEuwLdDik/14dZSHa1ttCgRAAAAALjf3Jz9puPLkjtpWCq7InsCjRvgAt08LFmhtpN/dRqb7Vq8/uBZrgAAAAAA37WtuOq0ERFsAe45NG6AC9Q5KlSTL00w1bLzCsScbwAAAAD+aF5Ovum4a3SYrh/U3ZowAYjGDdAOrR+X2lVWo/UFR60JAwAAAABucqimQe9uKjbV7hiZptBg2gmewr9poB1G9+yi1M6RphpDigEAAAD4m4W5BWpstjuPQ21Bum1k6lmugKvRuAHaISjIUFZmiqm2ZHOJquubLEoEAAAAAK7V1GLXgtUHTLUbBndT1+gwixIFJho3QDtNH56s4KCTw7jqmlr07sbis1wBAAAAAL7jwy0lKjvWYKrdM7aHRWkCF40boJ3io8N15SXxptpCHpcCAAAA4CfmthpKnJEeq4FJnawJE8Bo3AAXIavVkOJtxce0pajKojQAAAAA4BobCo5oY+FRU20Oq20sQeMGuAgT+nRVUkyEqbYwj1U3AAAAAHxb69U2STERmjwgwZowAY7GDXARbEGGZoxINtXe21is4w3NFiUCAAAAgItTWlWvD7eUmGp3jk5TsI0WghX4tw5cpJkjUnTKjGLVNDTrg80lbV8AAAAAAF7sldUH1Gx3OI/DQ4KUlZFylivgTjRugIvUPSZCl/drNaSYx6UAAAAA+KD6pha91mrTlZuHJSsmMtSiRKBxA7hA6+7zhoKj2ll6zKI0AAAAANA+720q1uHjjabanDHp1oSBJBo3gEtM6h+v+OgwUy07t9CiNAAAAABw4RwOx2lDicf3iVOfhGhrAkESjRvAJYJtQacNKV68vkj1TS0WJQIAAACAC7Nm/2HtKDE/OTCb1TaWo3EDuMitI1JNx8fqm/XRVoYUAwAAAPANc3P2m47Tu0TqilbzPOF5NG4AF0ntEqnxfeJMtYU8LgUAAADABxQertVn28tMtbvHpCvo1C10YQkaN4ALZWWYV93k7j+svRU1FqUBAAAAgPPz8qp8nbIDuDqEBWv68OS2L4DH0LgBXOjqAQnqEmXeJi87l63BAQAAAHiv4w3Nys4zPy0wY0SyosNDLEqEU9G4AVwoNDhIt7TqSr+1/qAamhlSDAAAAMA7LV5fpOr6ZuexYTCU2JvQuAFc7NaMFNPx4eONpz0rCgAAAADewG53aO7KfFPtyv7xSusSZU0gnIbGDeBivbp2UGaPzqZaNkOKAQAAAHihr3ZXaF/FcVNtztgeFqXBmdC4AdzgtkzzkOKv91Sq4FCtRWkAAAAA4Mzm5uSbjvslRGtMry7WhMEZ0bgB3ODagYnqFGEe5PX6WoYUAwAAAPAeeytqtHxXhak2e2y6DIMtwL0JjRvADcJDbJo2NMlUe2NtkZpa7BYlAgAAAACz+a1m28REhuimIUlnPhmWoXEDuMmsVo9LVVQ36Iud5RalAQAAAICTquqa9Oa6IlMtKyNVEaE2ixKhLTRuADfplxitoakxplp2Lo9LAQAAALDeorWFqm1scR7bggzdNTrNwkRoC40bwI1mZZhX3SzfVaHio3UWpQEAAAAAqcXu0LxWj0lde2miusdEWBMIZ0XjBnCjGwZ3U4ewYOex3SG9sZatwQEAAABY5/MdZSo6Yv6F8pyx6daEwTnRuAHcKDI0WFOHdDfV3sgrVIvdYVEiAAAAAIFubs5+0/GgpE4anhZrURqcC40bwM1aDykurqrXV6223AMAAAAAT9hRckyr9x021eawBbhXo3EDuNnApE4amNTRVFvIkGIAAAAAFmi92iauQ5iuv6ybRWlwPmjcAB6Q1WpI8dKd5So/Vm9RGgAAAACB6FBNg97ZWGyq3TEqVWHBbAHuzWjcAB4wdUh3RYSc/GbYYndo0boiCxMBAAAACDTZeYVqbLY7j0NtQbp9JFuAezsaN4AHRIeHaMpg8/LD1/MKZWdIMQAAAAAPaGqxa8GqA6baDYO7qWt0mEWJcL5o3AAektVqSHHB4Vqt2nfIojQAAAAAAslHW0tV2mpcw5wxPSxKgwtB4wbwkKEpMeqXEG2qvcaQYgAAAAAe0Hoo8Yi0WA1K7mRRGlwIGjeAhxiGoazMFFPt022lOlTTYFEiAAAAAIFgY+FRbSg4aqrNGctqG19B4wbwoGlDkxQafPKvXVOLQ4vXH7QwEQAAAAB/13q1TfdO4brm0gSL0uBC0bgBPCgmMlTfGZhoqi3MK5DDwZBiAAAAAK5XdqxeH2wuMdXuHJ2uYBvtAF/B/1OAh81qNaR4X8Vx5eUfsSgNAAAAAH/2yuoDaj5lN9vwkCDNajXCAd6Nxg3gYZk9Oqtn1yhTLZshxQAAAABcrL6pRa+tMb/XmDY0WTGRoRYlQnvQuAE8zDAMZWWYO9wfbClRVW2TRYkAAAAA+KP3NhXr0PFGU23O2HRrwqDdaNwAFrhlWLJCbIbzuKHZrrc3FFmYCAAAAIA/cTgcmpeTb6qN6x2nvgnR1gRCu9G4ASzQpUOYJg8wDynOzitkSDEAAAAAl8jdf1jbS46Zaqy28U00bgCLZLUaCLaztFobC49aEwYAAACAX5nbarVNWpdIXdEv3powuCg0bgCLjO0Vp5TOEaZadm6hRWkAAAAA+IvCw7X6dHupqXb36HQFBRltXAFvRuMGsEhQkKGsDPPW4O9vLlZ1PUOKAQAAALTfgtUHdMoO4OoQFqwZI5KtC4SLQuMGsNCM4cmyndL1rm1s0Xubii1MBAAAAMCX1TY2KzvXvAX49OHJig4PsSgRLhaNG8BC8R3DNam/+TlTHpcCAAAA0F5vrT+oY/XNzmPDkGaPSbcuEC4ajRvAYrNaDSnecrBKWw9WWZQGAAAAgK+y2x2al7PfVJvUL17pcVEWJYIr0LgBLDaxb7y6dQo31bLzCto4GwAAAADObMWeSu2tOG6qzRnbw6I0cBUaN4DFbEGGZo4wr7p5d0Oxahub27gCAAAAAE43t9Vqm74JHTS2dxeL0sBVaNwAXmBmRoqMU3bmq25o1gebS6wLBAAAAMCn7K2o0bJvKky12WN6yDDYAtzX0bgBvEBSTIQm9u1qqi3M5XEpAAAAAOfn5ZX5puNOESGaNjTJmjBwKRo3gJfIykg1Ha8vOKpdZdUWpQEAAADgK47VN+nNdUWmWlZmiiJCbRYlgivRuAG8xJWXxCuuQ5ipxqobAAAAAOfyRl6hjje2OI9tQYbuGp1uXSC4FI0bwEuE2II0Y0Syqfb2hoOqb2pp4woAAAAAga7F7tD8Vfmm2jWXJigpJsKaQHA5GjeAF8nKMO8udbS2SZ9sK7UoDQAAAABvt3RHmQoP15lqbAHuX2jcAF4krUvUadv18bgUAAAAgLbMzck3HQ9M6qgRabHWhIFb0LgBvEzrIcWr9x3Wvooai9IAAAAA8FY7So5p1b5DptoctgD3OzRuAC8z+dIExUaGmGqv5xValAYAAACAt5rXarVNXIcw3TC4mzVh4DY0bgAvExZs0y3DzEOK31xXpMZmu0WJAAAAAHibw8cb9c7Gg6ba7SNTFRbMFuD+hsYN4IWyMs1Dig8db9TnO8osSgMAAADA2yzMLVDDKb/cDbEZun1U6lmugK+icQN4od7x0cpM72yqMaQYAAAAgCQ1tdi1YNUBU23KZd0VHx1uUSK4E40bwEu1XnXz9Z5KFR6utSgNAAAAAG/x8dZSlR6rN9Vmj023JgzcjsYN4KW+M6ibOoYHO48dDoYUAwAAAJDm5uw3HQ9Pi9VlyTHWhIHb0bgBvFR4iE3ThiaZaovWFaq5hSHFAAAAQKDaVHhU6wuOmmpzWG3j12jcAF4sK9M8XKzsWIO+/KbCojQAAAAArNZ6tU23TuG65tJEi9LAE2jcAF7skm4dNTglxlTLZkgxAAAAEJDKj9Xrgy0lptqdo9MUYuOtvT/j/13Ay93Wakjxl9+Uq6SqzqI0AAAAAKzyyuoDampxOI/DQ4I0K4MtwP0djRvAy91wWXdFhdqcx3aHtGhtkYWJAAAAAHhafVOLXl1jXn0/bWiSYqNCLUoET6FxA3i5qLBg3TjEPKT49bxCtdgdbVwBAAAAwN+8v6lYh443mmqzx/SwKA08icYN4ANmtXpc6uDROq3YzZBiAAAAIBA4HA7Nzck31cb27qJ+idHWBIJH0bgBfMCgpE4a0K2jqZadW2hRGgAAAACelLv/sLaXHDPV5rDaJmDQuAF8gGEYp626+XxHmSqqGyxKBAAAAMBT5q3MNx2ndo7UFf3jrQkDj6NxA/iIqUOTFB5y8q9ss92hN9cxpBgAAADwZ0VHavXJtlJT7e4x6bIFGRYlgqfRuAF8RMfwEN1wWXdT7fW8AtkZUgwAAAD4rQWrDujUH/mjQm2aMSLZukDwOBo3gA9p/bhU/qFard53yKI0AAAAANyptrFZC3PNW4DPGJGijuEhFiWCFWjcAD5kWGqs+sR3MNUW5jGkGAAAAPBHi9cf1LH6ZuexYZx4TAqBhcYN4EMMw1BWZqqp9snWUh0+3mhRIgAAAADu4HA4ThtKfEW/ePWIi7ImECxD4wbwMTcPTVJo8Mm/uo0tdi1ez5BiAAAAwJ+s2F2pPeU1ptqcsenWhIGlaNwAPiY2KlTXDUw01bLzCuVwMKQYAAAA8Bdzc/abjvvEd9C43nEWpYGVaNwAPigrw/y41J7yGq07cMSiNAAAAABcaV9Fjb78psJUmz02XYbBFuCBiMYN4ING9ex82rOtC3MZUgwAAAD4g/mtZtt0igjRtKFJ1oSB5WjcAD7IMAzdmmHeGvyDLcWqqmuyKBEAAAAAVzhW36Q315lnWGZlpCgyNNiiRLAajRvAR90yLFnBQSeXStY32fXuxoMWJgIAAABwsRatLdLxxhbncZAh3Tk6zcJEsBqNG8BHdY0O0+RLE0y1hbkMKQYAAAB8VYvdcdpjUtdcmqjk2EhrAsEr0LgBfFjrIcU7So5pc1GVRWkAAAAAXIwvdpar4HCtqTZnbA+L0sBb0LgBfNi43nFKjo0w1bLzCixKAwAAAOBitN4C/NLuHZWRHmtRGngLGjeADwsKMnTrCPOQ4vc2FqumodmiRAAAAADaY2fpMa3ce8hUmzO2B1uAg8YN4OtmjEjRKTOKdbyxRe9vKrYuEAAAAIALNi8n33Qc1yFUUwZ3syYMvAqNG8DHJXYK16T+8aZadi6PSwEAAAC+4vDxRr29wbxD7G0j0xQWbLMoEbwJjRvAD8zKNA8p3lRUpe3FxyxKAwAAAOBCLMwtUEOz3XkcYjN0x6jUs1yBQELjBvADE/t2VWLHcFONIcUAAACA92tqsWvBqgOm2g2XdVd8dHgbVyDQ0LgB/ECwLUgzRySbam9vOKi6xhaLEgEAAAA4Hx9vLVXpsXpTbfaYdGvCwCvRuAH8xMyMFJ06cL66vlkfbimxLhAAAACAc5q3Mt90PCw1RoNTYizJAu9E4wbwE8mxkRrfp6uptpAhxQAAAIDX2lx0VOsOHDHV5oztYVEaeCsaN4AfmZWRYjpee+CIdpdVW5QGAAAAwNnMbbUFeGLHcF07MNGaMPBaNG4AP3LVgATFdQgz1bLzCi1KAwAAAKAt5cfqtWRzsal25+g0hdh4mw4z/kQAfiTEFqTpw81DihevL1JDM0OKAQAAAG/yypoCNbU4nMdhwUG6LZMtwHE6GjeAn8lq9bjUkdomfbKtzKI0AAAAAFpraG7Ra2vMW4BPG5qk2KhQixLBm9G4AfxMelyURvfsYqplM6QYAAAA8BrvbypRZU2jqTZ7bLo1YeD1aNwAfigr07zqZuXeQ8qvPG5RGgAAAADfcjgcmpuz31Qb06uL+id2tCgRvB2NG8APXXNpomIiQ0w1hhQDAAAA1svLP6JtxcdMNbYAx9nQuAH8UHiITbcMMw8pfnNdkZpa7BYlAgAAACDptNU2qZ0jNal/vEVp4Ato3AB+alarx6Uqaxq0dAdDigEAAACrHDxap0+2lZpqd41Oky3IsCgRfAGNG8BP9Y6P1oi0WFNtYS6PSwEAAABWeXlVvuwndwBXVKhNM1vtCgu05pHGTVBQkIKDg7V9+/bzvmbv3r3O6wC0T1Zmqun4q90VKjpSa1EaAAAAIHDVNjYru9UvUqcPT1bH8JA2rgBO8NiKG4fDce6TXHgdAOn6Qd0UHX6y+elwSG8wpBgAAADwuLc3HFRVXZOpdveYdGvCwKd4/aNShsGzfkB7RYTadNOQJFPtjbVFamZIMQAAAOAxDodD83LyTbUr+nVVz64drAkEn+K1jZvKykpJUlRUlMVJAN82q9XjUqXH6rV8V4VFaQAAAIDA8/WeSu0urzHV2AIc58ujjZvzXT1z/PhxPfvss5KkXr16uTMS4PcGdO+owcmdTDWGFAMAAACeM7fVapve8R00vk+cNWHgc9wy+bdnz55nrE+ePFkhIWcfvNTQ0KDy8nLZ7XYZhqEpU6a4IyIQULIyU7WpaIvz+MtvylV2rF4JHcMtTAUAAAD4v/2Vx/XFznJTbfaYdMaC4Ly5pXGTn59/Ws3hcOjgwYMX9DqjRo3Sf/7nf7ooFRC4pgzurt8u2a7axhZJUovdoUVrC/WDSX0sTgYAAAD4t/kr803HHcODdfOwpDOfDJyBWxo3d999t+l4/vz5MgxDN954o2JiYtq8zjAMhYeHq1u3bhozZowmTZpEFxJwgQ5hwbpxcHdln7KjVHZeoR64vLeCgvg7BgAAALjDsfomLVprHlMwKzNVkaFueSsOP+WWPy1z5841Hc+fP1+S9MQTT2jAgAHuuCWAc8jKTDU1boqO1OnrPZWa0LerhakAAAAA/7VobZGO/3vVuyQFGdKdo9MsTARf5JE232OPPSZJio+P98TtAJzB4OROuqRbR+0oOeasZecV0LgBAAAA3KDF7jjtManJAxKVHBtpTSD4LI82bgBYxzAMzcpM0aPvbnPWPttepsqaBsV1CLMwGQAAAOB/vtxZroLDtabanLHp1oSBT/PoduAArDV1SJLCQ07+tW9qceitdUUWJgIAAAD809yV+03HA7p1VGaPzhalgS9z6YqbgoIC5+epqalnrLfHqa8FoP06RYToO4O6afH6kzu8ZecV6r4JPRkEDgAAALjIN6XVytlzyFSbM5YtwNE+Lm3c9OjRQ9KJRzKam5tPq7dH69cCcHFmZaaaGjf7K49r9b7DGt2ri4WpAAAAAP8xr9Vqmy5RoZoyuLtFaeDrXPqolMPhcH60VW/PhzuUl5dryZIlevTRR3XdddcpLi5OhmHIMAzNnj3bZfd5/PHHna97ro9ly5a57L5AW0akxap3fAdTLTvv4lbFAQAAADjhyPFG0y9KJen2kakKD7FZlAi+zqUrblpvA36uupUSEhKsjgBYwjAMZWWk6Hcf7HDWPtpaql/XNiomMtTCZAAAAIDvW5hXoIZmu/M4xGbojlFsAY72c2nj5u67776gurdITU1V//799emnn7r1Plu2bDnr1y/mkTLgQtw8LFl//PgbNbac+A9KY7Ndi9cf1D3j+DMIAAAAtFdTi10LVh0w1a4f1E3xHcMtSgR/4NLGzc9+9jMZhqGHH35Y8fHxrnxpl3v00UeVkZGhjIwMJSQkKD8/3+2Nk4EDB7r19YHz1TkqVNcMTNT7m4qdtey8AgamAQAAABfhk22lKqmqN9XmjOWXo7g4Lp1x8/TTT+vpp59WZWWlqd6jRw/16tVLe/bsceXtLsqvf/1r3XDDDTwyhYA1KyPFdLyrrEbrC45aEwYAAADwA3Nz8k3HQ1NjNDglxpIs8B8ubdy05cCBA8rPz1djY6MnbgfgPIzq2UVpXSJNtYW5DCkGAAAA2mNz0VGtO3DEVGO1DVzBpY2byMgTbwJbr7gB4H2Cggzd2mrVzZLNxTpW32RRIgAAAMB3zWu12iaxY7iuG5hoTRj4FZc2bnr37i1Jevnll922jbcvmzx5suLj4xUaGqr4+Hhdfvnl+v3vf68jR46c+2LADaYPT1Zw0MmZNvVNdr27sfgsVwAAAABorby6Xu9vNv8cfefoNIXYPPKQC/ycS4cTT5s2TZs3b9bcuXP10UcfqWfPngoJCXF+fc6cOYqKirqg1zQMQ0uXLnVlTMt89tlnzs8rKiq0fPlyLV++XH/4wx80b948TZ06tV2vW1RUdNavl5SUtOt14f/io8N11SUJ+nhbqbOWnVugO9muEAAAADhvr64uUFPLycULYcFBmpWZamEi+BOXNm4efvhhffrpp1q1apVKSkpMDQOHw6G8vLzzfi3DMORwOPxih5tBgwbppptuUmZmprp3766mpiZ98803evXVV/Xpp5/q6NGjuuWWW/T+++/ruuuuu+DXT0lJOfdJQBuyMlNMjZttxce0pahKg5I7WZgKAAAA8A0NzS16dY15C/CbhiSpc1SoRYngb1zauAkPD9fy5cu1aNEiff755zp48KAaGhq0fPlyGYah4cOHX/CKG1/3k5/8RI8//vhp9ZEjR+quu+7SP//5T/3Hf/yHWlpadO+992rv3r0KDw/3fFAErPF9uiopJkIHj9Y5awvzCjQoeZCFqQAAAADfsGRTiSprzBvxzBmXbk0Y+CWXNm4kKTg4WLNmzdKsWbOctaCgE8/1zZs3TwMGDHD1Lb1aTEzMWb/+/e9/X3l5eXrxxRdVXFyst956S7fffvsF3aOwsPCsXy8pKVFmZuYFvSYChy3I0MwRKfrz57uctXc3HNR/fecSRYW5/FsEAAAA4DccDofmrtxvqo3u2UX9EztalAj+iElJXuD73/++8/Ply5df8PXJycln/ejWrZsr48IPzcxI1ikzinW8sUVLNjOkGAAAADibtQeOaOvBY6banLHp1oSB3/JI42b//v3at2+f+vbt64nb+ZxTVyEdPHjQwiQIVN06ReiKfvGm2sLcs6/kAgAAAALd3BzzapuUzhG68pIEi9LAX3mkcZOWlqa0tDQFB/PYxZn4wwBm+L6sVlPvNxYe1c7SY22cDQAAAAS2g0fr9Mm2MlPt7tHpsgXx/g6uZUknZd26dfr888+1detWHT58WJLUuXNnDRw4UFdddZWGDx9uRSzLbN++3fl59+7dLUyCQHZFv65K6BimsmMNzlp2bqEev/FSC1MBAAAA3unlVflqsZ/cAjwy1KYZI9jxF67n0cbNli1bdN999yk3N7fNc375y19q5MiR+uc//6lBgwJjV5t//vOfzs8nTpxoYRIEsmBbkGYMT9Ffv9zjrC1eX6T/d11/hYfYLEwGAAAAeJe6xhZltxotMH14sjpFhFiUCP7MY8OJP//8c2VmZio3N1cOh0MOh0PBwcFKSEhQQkKCgoODnfXVq1crMzNTS5cu9VS8dpk3b54Mw5BhGGfc8nvLli3as2fP6Ree4vnnn9cLL7wgSUpMTNS0adPcERU4L7dmmH9DcKy+WR9uKbEoDQAAAOCd3t5wUFV1Taba3WPSrQkDv+eRFTeVlZWaMWOGGhoaFBQUpO9+97v63ve+p6FDhzrn3rS0tGjDhg3617/+pZdeekkNDQ2aMWOGdu/erS5durg809dff21qqlRWVjo/37Nnj+bNm2c6f/bs2Rd8j3Xr1unee+/VFVdcoeuuu06DBg1Sly5d1NzcrJ07d+rVV1/Vp59+Kkmy2Wx6/vnnFRUV1a5/HsAVUjpHanyfOK3YffLvQ3ZuoW4elmxhKgAAAMB7OBwOzWu1Bfjl/bqqV9cOFiWCv/NI4+aZZ55RVVWVQkND9e677+qaa6457RybzaYRI0ZoxIgRuuWWWzRlyhRVVVXpmWee0W9+8xuXZ3rhhRc0f/78M34tJydHOTk5plp7GjfSiYbU559/rs8//7zNc7p06aIXX3xRU6ZMadc9AFealZlqatzk5h/WnvIa9Y7nP0QAAABAzp5D2lVWY6rNGdvDojQIBB55VOqDDz6QYRj6wQ9+cMamTWuTJ0/WD3/4QzkcDn3wwQceSOge3/nOd/Tiiy/q3nvv1fDhw5WcnKyIiAiFh4ere/fuuu666/TMM89o3759mjp1qtVxAUnSVZckqEtUqKn2el6BRWkAAAAA79J6C/BeXaM0oU+cRWkQCAyHw+E492kXJzY2VseOHdOXX36pCRMmnNc1X331lS6//HJ16tRJR44ccXNC/1ZUVKSUlBOzSwoLC5WczGMvOLv//XCH/vnVPudx56hQrXpkksKCGVIMAACAwJVfeVxX/N8ynfou+rc3DdSdo9KsCwWv4o733x5ZcVNfXy9JFzS/5dtzGxoaznEmAFdrPaT48PFGfba9zKI0AAAAgHeYtzLf1LTpGB6sW4YlWRcIAcEjjZvExERJ0oYNG877mm/PTUhIcEsmAG3r2bWDRvbobKotzOVxKQAAAASu6vomvbmuyFTLykxVZKhHRscigHmkcTN+/Hg5HA79/ve/17Fjx855fnV1tf7whz/IMAyNHz/eAwkBtDYrM9V0nLPnkA4cOm5RGgAAAMBai9YWqaah2XkcZIhHpOARHmncfP/735ck7d+/XxMmTNDatWvbPHft2rWaOHGi9u7da7oWgGddOzBRnSJCTLXX8wotSgMAAABYp8Xu0PxV+aba1QMSlNI50ppACCgeWdM1duxYPfDAA3ruuee0ZcsWjRw5UpdeeqlGjhyp+Ph4GYahsrIyrVmzRtu2bXNe98ADD2js2LGeiAiglfAQm24elqS5OfnO2qJ1Rfrp1X0VYvNIzxcAAADwCsu+KdeBQ7WmGluAw1M89jDes88+q8jISD311FOy2+3aunWrqUkjSd9ucBUUFKSf//zn+v3vf++peADOYFZmqqlxU1HdoC92luuaSxOtCwUAAAB42Kk/E0vSJd06njYTEnAXj/3a3DAM/fGPf9TGjRt1//33q0+fPnI4HKaPPn366P7779fGjRudM24AWKdvQrSGpcaYatkMKQYAAEAA2VVWra/3VJpqc8am834VHuPx8dcDBw7U3/72N0lSY2Ojjhw5IkmKjY1VaGiop+MAOIeszFStLzjqPF62q0IHj9YpKSbCulAAAACAh7RebdMlKlQ3Du5uTRgEJI+suOnZs6d69uypv/71r6Z6aGioEhISlJCQQNMG8FI3XNZN0WEne7wOh/QGQ4oBAAAQAI7WNurtDeYtwG8bmarwEJtFiRCIPNK4KSoq0oEDBzRkyBBP3A6AC0WGBmvqUPNvFBatLVSL3WFRIgAAAMAzFuYWqr7J7jwODjJ0B1uAw8M80rhJTDwxyDQigkcrAF+UlZFqOi6uqtdXuyosSgMAAAC4X3OLXQtabQF+/WXdlNAx3JpACFgeadyMHDlSkk7bRQqAbxiY1EmDkjqZagsZUgwAAAA/9sm2MhVX1ZtqbAEOK3ikcXP//ffL4XDoz3/+s5qamjxxSwAulpWZYjpeurNc5cfq2zgbAAAA8G1zc/abjoemxmhISow1YRDQPNK4mTRpkh555BFt2rRJN9xwgwoLGWwK+JobB3dXxClD2FrsDi1aV3SWKwAAAADftKWoSmsPHDHVZo9JtyYMAp5HtgP/zW9+o7CwMA0aNEifffaZevbsqbFjx+qyyy5TbGysbLazT+R+9NFHPRETwFlEh4doyuBuemPtyWZNdl6B7p/YS0FBhoXJAAAAANeau9K82iahY5i+M6ibRWkQ6DzSuHn88cdlGCfe2BmGoZaWFq1YsUIrVqw4r+tp3ADeYVZmqqlxU3i4Tiv3HtK4PnEWpgIAAABcp6K6QUs2lZhqd45KU4jNIw+sAKfx2J88h8Ph/Gh9fK4PAN5hSEqM+idGm2oL8xhSDAAAAP/x6poDamw5uQV4aHCQZmWmnuUKwL080rix2+0X9QHAOxiGoawM85DiT7eV6lBNg0WJAAAAANdpaG7RK6vNv5i8aUh3dekQZlEiwIMrbgD4h2lDkxUWfPJbR1OLQ4vXH7QwEQAAAOAaH2wuUWWrX0qyBTisRuMGwAXpFBly2mC2hXkFPNYIAAAAn+ZwODQ3J99UG9Wzsy7p1tGaQMC/ua1xU1JSol/84hcaNGiQOnbsqKioKPXp00f33Xeftm/f7q7bAvCA1o9L7as4rtz9hy1KAwAAAFy8dQeOaMvBKlON1TbwBm5p3OTk5GjgwIF66qmntH37dtXU1Kiurk779u3Tiy++qKFDh+qVV15xx60BeEBmj87q2TXKVMvOK7QoDQAAAHDxWq+2SekcoasuSbAmDHAKlzdujh49qhkzZujIkSPOXaG6dOmixMRESSeWnzU1Nenee+/V1q1bXX17AB5gGIZmZZgn63+4pURVtU0WJQIAAADar/honT7eVmqq3T06XbYgw6JEwEkub9y8+OKLKi0tlWEYmjFjhvbu3auKigoVFxerrKxMDz30kCSpqalJTz75pKtvD8BDbh6WpBDbyf+QNTTb9faGIgsTAQAAAO3z8qoDarGfnNkYGWrTjBEpZ7kC8ByXN24++ugjSdL48eP1+uuvq0ePk88ExsXF6U9/+pPuu+8+ORwO57kAfE+XDmGafGmiqZadV8iQYgAAAPiUusYWLcw1bwF+y7BkdYoIsSgRYObyxs3WrVtlGIYeeOCBNs/54Q9/KEmqrKxUZWWlqyMA8JDWj0vtLK3WhsKj1oQBAAAA2uGdjQdVVWd+5H/22HRrwgBn4PLGzZEjRyRJffv2bfOcU7/27fkAfM+YXl2U0jnCVMtu9dsKAAAAwFud2AJ8v6k2sW9X9erawaJEwOlc3rhpajrRqQwNDW3znJCQk0vOvj0fgO8JCjKU1WrVzfubSlRdz99rAAAAeL+Vew9pV1mNqTaH1TbwMm7ZDhxA4JgxPNk0bb+uqUXvbSq2MBEAAABwflqvtunZNUoT+nS1KA1wZjRuAFyU+I7hurJ/vKmWnVtoURoAAADg/Bw4dFxLd5abanPGpCuILcDhZYLd9cJz5sxRVFTURZ9nGIaWLl3qymgAXGxWZqo+3V7mPN5ysEpbD1ZpYFInC1MBAAAAbZu3Ml+nbogaHR6sm4clWxcIaIPbGjdr164969cNwzjneQ6Hw3keAO81oW9Xde8UruKqemdtYW6Bnpg2yMJUAAAAwJlV1zdp0doiUy0rI0VRYW57iwy0m1selXI4HC75AOAbbEGGZoxIMdXe3Vis2sZmixIBAAAAbXtzXZFqGk7+rBpkSHeNTrcuEHAWLm/c2O12l360tLS4OiIAN5iZkaJTHweuaWjWks0l1gUCAAAAzsBud2j+ynxT7apLEpTSOdKaQMA5MJwYgEskxURoYl/zBP7s3AKL0gAAAABn9uU35co/VGuqzRnbw6I0wLnRuAHgMlmZqabj9QVHtaus2qI0AAAAwOnmtVpt0z8xWqN6drYmDHAeaNwAcJlJ/ePVNTrMVFvIqhsAAAB4id1l1Vqxu9JUu2dsDzbFgVejcQPAZUJsQZox3LyF4uL1B1XfxKwqAAAAWG9uq9U2naNCdeOQ7taEAc4TjRsALnVrhnl3qaq6Jn28tdSiNAAAAMAJR2sbtXi9eQvw2zJTFR5isygRcH5o3ABwqbQuURrXO85U43EpAAAAWC07r1D1TXbncXCQoTtHp1mYCDg/NG4AuFxWpnnVzZr9h7WvosaiNAAAAAh0zS12vdzqManvDOqmhI7h1gQCLgCNGwAud/WABHWOCjXVXs8rtCgNAAAAAt2n28tUXFVvqs0Zm25NGOAC0bgB4HJhwTbdMizJVHtzXZEam+1tXAEAAAC4z9yc/abjISkxGpoaa1Ea4MLQuAHgFrdmpJqODx1v1GfbyyxKAwAAgEC19WCV8vKPmGqstoEvoXEDwC16x3dQZnpnUy07jyHFAAAA8KyXWq22iY8O03UDu1mUBrhwNG4AuM2skeYhxSt2V6rwcK1FaQAAABBoKqobtGRTial256g0hQbzVhi+gz+tANzmuoHd1DE82FRjSDEAAAA85bU1BWpsOTlnMTQ4SLeNTD3LFYD3CT73Kedv0qRJrnw5SZJhGFq6dKnLXxeA+4WH2HTzsGTNO2XrxUXrCvWTq/oo2EbfGAAAAO7T2GzXK2sOmGpTB3dXlw5hFiUC2seljZtly5bJMAw5HI6Lfq1vX8cwDBckA2CVrMwUU+Om7FiDvvymQlcPSLAuFAAAAPzeB1uKVVHdYKrNGdvDojRA+7m0cTNhwgQaLQBM+id21JCUGG0sPOqsLcwtoHEDAAAAt3E4HJqbk2+qjezRWQO6d7QmEHARXL7iBgBam5WZYmrcLPumXCVVderWKcK6UAAAAPBb6wuOaHNRlanGahv4KoZMAHC7Gy7rrg5hJ/vEdof0Rl6RhYkAAADgz15qtdomOTaCFd/wWTRuALhdVFiwbhzS3VR7Y22hWuwXPw8LAAAAOFXx0Tp9vLXUVLt7dLpsQYz1gG+icQPAI2ZlmLddPHi0Tit2V1iUBgAAAP5qweoDpl8QRoTYNHNEioWJgItD4waARwxK7qRLWw2Dy84ttCgNAAAA/FFdY4sW5haYarcMT1KnyBCLEgEXz6WNG5vN5vKP4GCXzk8GYKGsTPOqm893lKm8ut6iNAAAAPA372w8qKO1Taba7DEMJYZvc2njxuFwuOUDgH+YOqS7IkJszuNmu0NvrmNIMQAAAC6ew+HQvFZDiSf07are8R2sCQS4iEuXszz22GOufDkAfqZjeIhuuKybFp3SrHk9r1D/MaGXghgWBwAAgIuwau8hfVNWbarNGZtuTRjAhWjcAPCorMxUU+PmwKFard53SGN6x1mYCgAAAL6u9RbgPeOiNLFPV2vCAC7EcGIAHjUsNUZ9E8zLVRfmMaQYAAAA7Xfg0HEt3Vlmqs0em86qbvgFr27cVFRU6JlnnrE6BgAXMgxDWa22Bv9ka6kOH2+0KBEAAAB83fyVB3TqeNTo8GDdMizZukCAC3ld46axsVGLFi3SlClTlJycrIceesjqSABc7OZhSQoNPvntp7HFrsXrGVIMAACAC1fT0KxFa80ruG8dkaKoMHYohn/wmsZNTk6Ovv/97ysxMVFZWVn68MMP1dTUxK5SgB+KiQzVdQMTTbWFuQX8fQcAAMAFe3Ntoaobmp3HhiHdPSbdukCAi1nagty/f79efvllvfLKK9q3b58kOd+4hYaG6qqrrtItt9xiZUQAbjIrM1Xvbix2Hu+tOK61B44oI72zhakAAADgS+x2h+avOmCqXXVJglI6R1qUCHA9jzduqqqq9Prrr2vBggVauXKlpJPNmvDwcF1zzTWaPn26pkyZoo4dO3o6HgAPGdmjs3rGRWlf5XFnbWFuAY0bAAAAnLdlu8q1/5SfJyW2AIf/8UjjpqWlRR999JFefvllLVmyRA0NDZJONGxsNptaWlpkGIbmzp2rW2+91RORAFjMMAzdmpGi//1op7P24ZYSPTblUnWKCLEwGQAAAHzF3FZbgPdPjNbonl2sCQO4iVtn3Kxfv14/+clPlJSUpKlTp+qtt95SfX29HA6HBg8erCeffFKFhSeHSBkGW7UBgeSW4ckKsZ38e1/fZNe7Gw9amAgAAAC+YndZtVbsrjTV5oxN530l/I7LV9wUFxfrlVde0YIFC7R9+3ZJJx+FSklJ0W233aY777xTAwYMcPWtAfiYuA5hunpAgj7cUuqsvbamQHeOSuM/uAAAADireSvzTcexkSGaOiTJmjCAG7m8cZOamiqHw+Fs1nTq1EnTp0/XHXfcoYkTJ7r6dgB8XFZGqqlxs7O0WpuKqjQkJca6UAAAAPBqVbVNWrzevFL7tpGpCg+xWZQIcB+XN27sdrsMw1B0dLSefPJJ3XXXXQoLC3P1bQD4iXG945QcG6GiI3XOWnZuAY0bAAAAtCk7r0B1TS3O4+AgQ3eOSrcuEOBGbptxU1NTox/+8IeaNWuWFi9erMbGRnfdCoAPCwoylJWRYqq9t6lYNQ3NFiUCAACAN2tusevlVluAXzeomxI7hVuUCHAvlzdu5s6dq8svv1yS1NjYqHfffVczZsxQYmKi7rvvPi1fvtzVtwTg42aMSJEt6ORMm9rGFr2/qdjCRAAAAPBWn20v08GjdaYaW4DDn7m8cXP33Xdr6dKlOnDggH73u9+pX79+cjgcOnr0qF588UVNmjRJaWlpeuSRR5zDiwEEtoSO4bqiX7yplp1bYFEaAAAAeLPWW4APTonRsNRYa8IAHuC2R6WSk5P1y1/+Utu3b9eaNWv0wAMPqHPnznI4HCosLNQf//hHDRo0SEOHDnVXBAA+ZFam+XGpTUVV2lZcZVEaAAAAeKOtB6uUm3/YVLuH1Tbwc25r3JwqIyNDf/3rX1VSUqK3335b06ZNU0hIiBwOhzZt2uTc9vd///d/9fTTT6uggN+0A4FmYt+uSuxofi45O7fQojQAAADwRq1X28RHh+m6gd2sCQN4iEcaN98KDg7W1KlT9dZbb6mkpETPPvusMjMznduHb968WQ899JB69OihzMxM/fGPf9TevXs9GRGARYJtQZrZakjxOxsPqq6xpY0rAAAAEEgqqhtOm4N4x6g0hQZ79G0t4HGW/QmPjY3Vgw8+qNWrV2vnzp165JFHlJKS4mzirFu3To888oj69etnVUQAHjZzRLKMkzOKVV3frA+2lFgXCAAAAF7jtTUFamyxO49DbUG6bWSqhYkAz/CK1mTfvn31xBNPKD8/X1988YVmz56tDh06OJs4AAJDcmykJvTpaqoxpBgAAACNzXa9ssa8BfiNQ7orrkOYRYkAz/GKxs2pLr/8cr300ksqLS3VggULdPXVV1sdCYAHtR5SvPbAEe0uq7YoDQAAALzBh1tKVFHdYKqxBTgChdc1br4VERGh22+/XR9//LHVUQB40JWXJJz2m5OFDCkGAAAIWA6HQ3Nz9ptqmT0669LunSxKBHiW1zZuAASmEFuQpg9PNtUWbyhSfRNDigEAAALR+oKj2lRUZaqxBTgCCY0bAF4nq9XuUkdrm/TJtlKL0gAAAMBKrVfbJMVE6OoBiRalATyPxg0Ar5MeF6UxvbqYatk8LgUAABBwSqrq9NFW8y/w7h6TJluQ0cYVgP+hcQPAK2Vlmrd2XLXvkPIrj1uUBgAAAFZYsOqAWuwndxqOCLHp1hFsAY7AQuMGgFe65tIExUaGmGrZeay6AQAACBT1TS1amFtgqt08LEmdWv2MCPg7GjcAvFJYsE03DzMPKX5zXaEam+0WJQIAAIAnvbPhoI7UNplqbAGOQETjBoDXmpVpHlJcWdOopTvKLEoDAAAATzmxBXi+qTa+T5x6x0dbEwiwEI0bAF6rd3y0MtJjTbWFPC4FAADg91btPaRvyqpNtXvG9rAoDWAtGjcAvFpWhnn43IrdFSo8XGtRGgAAAHjC3JX5puOecVGa2LerNWEAi3mkcXPbbbfp+eef1zfffOOJ2wHwI98Z1E3R4cHOY4dDWrSWVTcAAAD+quBQrT5v9Xj83WPSFcQW4AhQHmncZGdn6/7779eAAQPUvXt3ZWVl6R//+Id27NjhidsD8GERoTZNG5pkqr2xtkjNLQwpBgAA8EfzV+XLcXIHcEWHBeuW4cltXwD4OY80bvr27SuHwyGHw6HS0lItWrRIDz74oAYOHKjExETNnDlTzz33nLZt2+aJOAB8TOvHpUqP1WvZNxUWpQEAAIC71DQ0641WMw1nZqSoQ1hwG1cA/s8jf/p37typ8vJyLVu2TMuXL9eyZcucq23Ky8v11ltv6a233pIkdenSRRMmTNDll1+uiRMnatCgQZ6ICMCLDejeUYOTO2lTUZWzlp1XoKsGJFiYCgAAAK721roiVTc0O48NQ7p7dLp1gQAv4LG2ZXx8vGbOnKmZM2dKkioqKrR8+XLnx7Zt2+RwOFRZWam3335bb7/9tqQTjZzy8nJPxQTgpWZlpmpT0Rbn8Rc7y1VaVa/ETuEWpgIAAICr2O0OzWs1lPiqSxKU2iXSmkCAl7BsV6muXbtq+vTpevbZZ7V582bnypsHH3xQHTt2dD5adejQIasiAvAiUwZ3V1SozXlsZ0gxAACAX1m+q0L7K4+banPGpFsTBvAiXrEd+ObNm/Xqq69qwYIFWrhwoY4dOybDYGI4gJOiwoJ145DuptrrawtltzvauAIAAAC+5KWc/abjfgnRGt2ri0VpAO9hyYSnzZs3a9myZVq2bJm++uorHTlyRJLk+Pfo8LCwMI0aNUqXX365Lr/8cisiAvBCWRmpWph7cpVN0ZE6fb2nUhP6drUwFQAAAC7WnvJqrdhdaarNGZvOL/QBeahxc65GTXh4uKlRM3LkSIWFhXkiGgAfcllyJ13SraN2lBxz1hbmFtC4AQAA8HFzc/JNx7GRIbppaJI1YQAv45HGzZAhQ5ydUofDoYiIiNMaNaGhoZ6IAsCHGYahWZkpevTdbc7aZ9vLVFHdoK7RNHsBAAB8UVVtkxavP2iqzcpMVXiIrY0rgMDi8UelbrzxRj388MMaNWoUy94AXLCpQ5L0Px/uUH2TXZLUbHforfVF+o+JvSxOBgAAgPZ4fW2B6ppanMe2IEN3jk6zMBHgXTwynDg0NNS5S9T777+vcePGqUuXLpo6daqeeuoprV+/3vnYFACcTaeIEF0/qNWQ4rxCvocAAAD4oOYWu+avPGCqXTcwUd06RViUCPA+HllxU1VVpTVr1mjZsmVavny5Vq9eraNHj+r999/XkiVLJEmdOnXSuHHjnI9PDR06lBU5AM5oVmaK3lpf5DzeX3lcq/cdZtcBAAAAH/P5jjIdPFpnqs0Z28OiNIB38kjjJiwsTBMmTNCECRMkSY2NjcrNzXU2clatWqWjR49qyZIl+uCDDySdbORcccUV+ulPf+qJmAB8xPC0WPWO76A95TXOWnZeAY0bAAAAH/NSq6HEg5M7aVhqjCVZAG9lOLzg+YLm5mbl5uZq+fLlWrZsmXJyclRbWyvpxDDSlpaWc7wCzqaoqEgpKSmSpMLCQiUnJ1ucCLh4L6zYp999sMN5HGoL0ppfXqnYKAadAwAA+IJtxVW6/i9fm2pP3zqE3aTg09zx/tsjM27OpbGxUTU1NaqurlZ1dbWampp4TArAWd08LFmhtpPfwhpb7Fq84eBZrgAAAIA3ab0FeNfoMH1nUDdrwgBezOO7SklSbW2tvv76ay1btkzLli3TunXr1Nzc7Pz6t4uAIiMjNWbMGCsiAvBynaNCde3ARL23qdhZy84t0D1j02n8AgAAeLnKmga9t7HYVLtjZJpCg71ibQHgVTzSuDlbo+bUJ7WioqI0ZswYXX755Zo4caIyMzMVHGxJbwmAD8jKTDE1bnaX12h9wRENT+tsYSoAAACcy2trCtTYYnceh9qCdNvIVAsTAd7LI12R2NjYMzZqOnTooLFjxzobNRkZGbLZbJ6IBMAPjO7ZReldIpV/qNZZW5hbSOMGAADAizU227VgtXkL8CmDu6trdJhFiQDv5pHGTVNTkyQpOjraueX3xIkTNXz4cBo1ANrNMAzdmpGqP3y801lbsrlYj04ZoI7hIRYmAwAAQFs+2lqiiuoGU23O2HRrwgA+wCONmz/96U+aOHGihg0bpqAgnlkE4DrThyfr/z79Rs32E6v56pvsenfDQd05Ot3aYAAAADij1luAZ6Z31sCkTtaEAXyAR7ooDz30kEaMGEHTBoDLdY0O01WXJJhqC3MLTY9lAgAAwDusLziiTYVHTTVW2wBnRycFgM+b1WqQ3faSY9pysMqiNAAAAGhL6y3Ak2IidPWAhDOfDEASjRsAfmB87zglxUSYagtzCy1KAwAAgDMprarXR1tKTLW7Rqcp2MbbUuBsPL7X9t69e/Xee+9p06ZNqqysVF1d3VkfaTAMQ0uXLvVgQgC+JijI0K0ZKXrqs13O2nsbD+q/r79EUWEe/zYHAACAM1iwOt85l1CSIkJsyspgC3DgXDz2jqa2tlYPPvigFixYcFqjxuFwyDCM02qSTqsDwJnMGJGspz/fpW9/Fjje2KIlm4t1Kz8MAAAAWK6+qUWvrSkw1aYNS1KnSHYCBc7FI2vSHA6Hpk2bppdffll2u11dunTR4MGDnc2Z8ePHa8CAAbLZbM5av379NHHiRE2YMMETEQH4uG6dInRFv3hT7TUelwIAAPAK7248qCO1TabanDHp1oQBfIxHGjeLFi3SZ599Jkl67LHHVFpaqpdfftn59eXLl2vLli06cuSInnrqKUVFRenw4cP67W9/qy+//NITEQH4gaxM8+qaTYVHtaPkmEVpAAAAIJ34RX7rocTj+8SpT0K0NYEAH+ORxs1rr70mSRo9erQee+wxBQUFnfERqKioKP3kJz/R0qVLVV1drZtvvlnFxcWeiAjAD1zRr6sSOoaZatm5BW2cDQAAAE9Yte+QdpZWm2psAQ6cP480btauXSvDMPS9733vvM7PyMjQ/fffr8rKSv3lL39xczoA/iLYFqSZI1JMtbc3HFR9U4tFiQAAANB6tU2PuChd3jf+zCcDOI1HGjeVlZWSpJ49ezprISEnh1DV1dWdds31118vSVqyZImb0wHwJzNHpOjUBX3H6pv1YattJwEAAOAZhYdr9fmOMlPt7tFpCgpiExrgfHmkcRMcfGLzqujok88wnvp5aWnpadd06tRJklRYyHBRAOcvpXOkxvWOM9WyGVIMAABgifkr83XqpsLRYcGa3mqFNICz80jjpnv37pKkiooKZy0xMVERERGSpPXr1592ze7duyVJzc3NHkgIwJ/MajWkODf/sPaUV7dxNgAAANzheEOzXl9r/gXajBEp6hAWbFEiwDd5pHEzePBgSdKWLVucNcMwNHLkSEnSc889Zzq/qalJTz31lCSpT58+nogIwI9cdUmCukSFmmqsugEAAPCst9YXqbr+5C/iDUOazRbgwAXzSONm0qRJcjgc+vjjj031e+65Rw6HQ8uWLdPll1+uv/3tb/rjH/+ozMxM50DjmTNneiIiAD8SGhyk6SOSTbW31hepoZkhxQAAAJ5gtzs0r9VQ4iv7Jyi1S6Q1gQAf5pHGzbRp02QYhr788kvt27fPWb/jjjt07bXXyuFwaMWKFfrRj36kRx55RJs3b5YkDRkyRD/72c/ckqm8vFxLlizRo48+quuuu05xcXEyDEOGYWj27NluuefChQs1efJkJSYmKjw8XGlpabrjjju0atUqt9wPCGRZGebHpY7UNunTbWVtnA0AAABXWr67Qvsqj5tqbAEOtI9HHi5MTExUU1OTHA6HbDab6Wtvv/22fve73+nFF190DimOiYnR7bffrieeeELh4eFuyZSQkOCW1z2Turo6TZ8+XR9++KGpXlBQoFdffVULFy7Uo48+qscee8xjmQB/1yMuSqN6dtbqfYedtey8Ak0Z3N3CVAAAAIGh9Rbg/RKiNaZXF2vCAD7OIytuJCkoKOi0po0khYWF6be//a2Ki4tVWVmp0tJSHTp0SM8++6w6duzokWypqamaPHmy217/nnvucTZtrrjiCr3zzjvKzc3Viy++qF69eslut+vxxx/X888/77YMQCBqPaQ4Z88hHTh0vI2zAQAA4Ap7ymv01a4KU2322HQZBluAA+3hkcZNQUGBCgoKdPjw4bOe17lzZ8XHx3vkL/Sjjz6q999/X6WlpTpw4ID++c9/uuU+X3zxhbKzsyVJU6ZM0WeffaapU6cqIyND99xzj1avXq3U1BNvLh9++GEdOXLELTmAQHTNpYmKiQwx1bLzGFIMAADgTvNW7jcdx0SG6KYhSRalAXyfRxo36enp6tGjh7OB4Q1+/etf64YbbnD7I1NPPvmkJCk4OFjPPffcaauO4uLi9Ic//EGSdPToUb3wwgtuzQMEkvAQm6YNNf+QsGhtkZpa7BYlAgAA8G9VtU16a91BU21WZqoiQk9/+gLA+fFI4yYiIkKSlJGR4YnbeY3q6motXbpUknTVVVcpOTn5jOfdfPPNzsfC3n77bY/lAwJB68elKmsatHRHuUVpAAAA/NsbawtV13RyJ09bkKE7R6VZmAjwfR5p3CQlnfiNd0tLYG3Fm5eXp8bGRknSxIkT2zwvNDRUo0aNcl7T1NTkkXxAIOibEK3habGmWnZegUVpAAAA/FeL3aH5q/JNtWsHJqp7TIQ1gQA/4ZHGzbeDf7/++mtP3M5rbN++3fl5//79z3rut19vbm7W7t273ZoLCDRZGSmm4+W7KnTwaJ1FaQAAAPzTZ9vLVHTE/DPWPWwBDlw0jzRufvzjHysiIkJPPvmkDh48eO4L/ERRUZHz87Yek/pWSsrJN5aFhRc2PLWoqOisHyUlJRcWHPAz11/WTdFhwc5jh0N6gyHFAAAALjU3xzyU+LLkThqWGtvG2QDOl0caN3369NFrr72m2tpajRo1Sq+99przESJ/Vl1d7fy8Q4cOZz03KirK+XlNTc0F3SclJeWsH5mZmRcWHPAzkaHBmjq0u6n2xtpCtdgdFiUCAADwL9uKq7Rmv3kX4TlsAQ64RPC5T7l4kyZNkiR17dpV+/fv15133qnvfve76tOnj2JjY0/baelUhmE4B/z6mvr6eufnoaGhZz03LCzM+XldHY9wAK6WlZGqV1afnG1TUlWv5bvKNam/e3eWAwAACATzcvJNx12jw3T9oO5nPhnABfFI42bZsmWmTqvD4VBDQ4O2bt3a5jWGYcjhcPh0hzY8PNz5+blWGDU0NDg//3YXrvN1rkerSkpKWHWDgDcwqZMuS+6kzUVVztrC3EIaNwAAABfpUE2D3t1UbKrdPjJVocEeecAD8HseadxMmDDBpxsw7RUdHe38/FyPPx0/ftz5+bkeq2rtXPNzAJyQlZGqzUVbnMdf7CxX+bF6xXcMP8tVAAAAOJvX1hSosdnuPA61Ben2kWwBDriKx1bcBKJTGypFRUUaMWJEm+eeumrm1EHFAFznxiHd9bsPtqu2sUXSiS0rF60r0oNX9LY4GQAAgG9qbLZrweoDptoNg7upa3RYG1cAuFCsXXOjAQMGOD/fuXPnWc/99uvBwcHq06ePW3MBgapDWLCmXGZ+1jo7r0B2hhQDAAC0y0dbS1Re3WCq3TO2h0VpAP9E48aNMjIynEOJly9f3uZ5jY2NWr16tfOakJAQj+QDAlFWpnlFW+HhOuXsrbQoDQAAgG97qdVQ4oz0WA1M6mRNGMBP0bhxo+joaF155ZWSpM8//1xFRUVnPG/x4sU6duyYJGnatGkeywcEoiEpMeqfGG2qZeeefcA3AAAATreh4Ig2FR411eaw2gZwOZfOuPnqq69c+XJOEyZMcMvrXqx58+Zpzpw5kqTHHntMjz/++Gnn/PznP9dHH32k5uZmPfjgg1q8eLFp+/PKyko9/PDDkqSYmBjde++9HskOBCrDMDQrM1WPvbfNWft0e6kO1TSoSweexQYAADhfc1uttkmKidDkAezYCbiaSxs3l19+uct3jzIMQ83NzS59TUn6+uuvtWfPHudxZeXJRyX27NmjefPmmc6fPXt2u+4zadIkZWVlKTs7W++9956uvvpq/eQnP1H37t21ZcsWPfHEEyooKJAk/eEPf1BsbGy77gPg/N00JEn/8+EONfx794OmFofeWl+k+yb0sjgZAACAbyitqteHW0pMtTtHpynYxkMdgKu5fFcph8M3hny+8MILmj9//hm/lpOTo5ycHFOtvY0bSXrppZd07Ngxffjhh/ryyy/15Zdfmr4eFBSkX/3qV7rvvvvafQ8A569TZIiuH9RNizccdNay8wr1vfE9Xd58BgAA8EevrD6g5lM2eAgPCVJWBrvjAu7g0sZN64bEqRobG/Xf//3fysvLU9euXTVz5kxlZmYqIeHEUrqysjLl5eXpjTfeUHl5uTIyMvTEE0/4xaDeiIgIffDBB3rttdc0b948bdq0SUePHlVCQoLGjx+vH/zgBxo9erTVMYGAkpWZamrc7Ks4rtz9hzWyZxcLUwEAAHi/+qYWvZZbYKrdPCxZMZGhFiUC/Jvh8MASGYfDoe985zv69NNPdc899+jpp59WVFTUGc+tra3VT37yE73wwgu69tpr9eGHH7o7nt8rKipSSsqJ7ndhYaGSk5MtTgRYz+Fw6KqnlmtvxXFn7aYh3fV01lALUwEAAHi/N/IK9Z9vbTbVPv3pBPVNiG7jCiBwuOP9t0ceQHzxxRf1ySef6KqrrtK//vWvNps2khQZGannn39eV199tT755BM9//zznogIIMAYhqGsjFRT7cOtpTpa22hRIgAAAO/ncDj0Us5+U21c7ziaNoAbeaRxM2/ePBmGoQceeOC8r3nwwQflcDjanEMDABfrluHJCj1lgF5js11vn/L4FAAAAMxW7zusnaXVptqcsenWhAEChEcaNzt37pQkpaamnuPMk75dWvTttQDgap2jQjX5UvOWldm5hT4zZB0AAMDT5rZabZPeJVJX9Iu3KA0QGDzSuKmvr5d04vmu8/XtuQ0NDW7JBACSNCvT3FD+pqxaGwqPWhMGAADAixUertVnO8pMtbvHpCsoiF05AXfySOOmd+/ekqR//OMf533Nt+f26tXLLZkAQJJG9+yi1M6Rplp2q10SAAAAIL28Kl+nLkzuEBas6cPZ+ARwN480bmbOnCmHw6FPPvlEDzzwgHMFzpk0NDToBz/4gT7++OMTw0OzsjwREUCACgoydGtGiqn2/qYSVdc3WZQIAADA+xxvaFZ2nvkJihkjkhUdHmJRIiBweGQ78Pr6eg0bNkw7d+6UYRhKSEjQzJkzlZGRofj4eBmGobKyMuXl5WnRokUqLS2Vw+FQ//79tWHDBoWFhbk7ol9jO3Dg7MqP1Wv0779Qi/3kt8Pf3TRQd4xKszAVAACA91iwKl+/eneb89gwpGU/v1xpXdreMRgIRO54/x180a9wHsLDw/Xll1/q+uuv1/r161VaWqpnn332jOd+20caOnSolixZQtMGgNvFdwzXVZfE65NtJ5/Zzs4roHEDAAAgyW53aO7KfFPtyv7xNG0AD/HIo1KSlJCQoDVr1ujZZ5/VgAED5HA4zvhxySWX6C9/+Ytyc3PVrVs3T8UDEOCyWg0p3nrwmLYerLIoDQAAgPf4aneF9lUcN9XmjO1hURog8Hhkxc23bDabHnzwQT344IMqLS3Vli1bdPjwYUlSbGysBg0aRLMGgCUm9OmqpJgIHTxa56wtzC3QE9MGWZgKAADAenNz8k3HfRM6aEyvLtaEAQKQRxs3p0pMTFRiYqJVtwcAE1uQoRkjkvX057udtXc3Fuu/rr9EkaGWfasEAACw1J7yGi3fVWGqzR7TQ4bBFuCAp3jsUSkA8HYzR6Qo6JSfQWoamrVkU4l1gQAAACw2v9Vsm5jIEE0bmmRNGCBA0bgBgH/rHhOhy/vFm2oL8wosSgMAAGCtqromvbW+yFTLykhVRKjNokRAYPLo+v/m5mZ98MEHWrFihfbt26fq6mq1tLSc9RrDMLR06VIPJQQQ6LIyUvTFznLn8YaCo/qmtFr9EqMtTAUAAOB5b+QVqrbx5Ps1W5Chu0az6ybgaR5r3Hz99de68847VVBw8rfX3279fSaGYcjhcPDsJACPmtQ/XvHRYSqvbnDWFuYW6PEbL7UwFQAAgGe12B2avyrfVLv20kR1j4mwJhAQwDzSuNm5c6euvfZa1dXVyeFwKDQ0VH369FHnzp0VFMTTWgC8R7AtSDNGJOtvX+511t7ecFD/77r+Cg9hWTAAAAgMn+8oU9GROlNtzth0a8IAAc4jjZv/+Z//UW1trWw2m37961/rRz/6kTp06OCJWwPABbt1RKqpcVNV16SPt5bqJgbxAQCAADE3Z7/peFBSJw1Pi7UoDRDYPLLc5YsvvpBhGPrxj3+sX/7ylzRtAHi11C6RGtc7zlR7LZchxQAAIDDsKDmm1fsOm2pzxqYzxgKwiEcaN5WVlZKkadOmeeJ2AHDRZmWmmo5z9x/W3ooai9IAAAB4TuvVNnEdwnT9Zd0sSgPAI42brl27SpIiIhhkBcA3XD0gQV2iQk211/MKLUoDAADgGYdqGvTOxmJT7faRqQoLZtYfYBWPNG7GjRsnSdq6dasnbgcAFy00OEi3DE821d5aV6TGZrtFiQAAANxvYW6B6eedEJuh20elnuUKAO7mkcbNz372M9lsNj3zzDNqbm72xC0B4KLdmpFiOj50vFGfbS+zKA0AAIB7NbXYtWD1AVNtymXdFR8dblEiAJKHGjcZGRl6+umntWnTJt18883OmTcA4M16de2gzB6dTbXsPIYUAwAA//ThlhKVHWsw1eaM7WFRGgDfcul24L/5zW/O+vXMzEwtWbJEaWlpuvrqq9W/f39FRkae83UfffRRV0UEgAsyKzNFuftP7qqwYnelCg7VKrXLub93AQAA+JK5Ofmm4xFpsRqU3MmaMACcDIfD4XDViwUFBZ3XFnEOh+OCtpJraWm5mFgBr6ioSCkpJx75KCwsVHJy8jmuAPCt+qYWjfyfpaqqa3LWHryil35xTX8LUwEAALjWhoIjmvbcSlPtb7cNYzcp4AK54/23yx+Vcjgc5/w43/NOPR8ArBAeYtO0oUmm2qK1RWpuYUgxAADwH/NW5puOu3cK1zWXJlgTBoCJSxs3drvdLR8AYKVZmeadFMqrG/TFznKL0gAAALhW2bF6fbC5xFS7c3S6gm0eGYkK4Bz4mwgA59AvMVpDU2NMtey8QmvCAAAAuNgrqw+o2X7ySYfwkCDNykw5yxUAPInGDQCch1kZ5lU3y74pV/HROovSAAAAuEZ9U4teW2PeNXPa0GTFRIZalAhAax5p3PTo0UO9evXSnj17zvuagoIC9ezZU7169XJjMgA4PzcM7qYOYSc34rM7pDfWsuoGAAD4tvc2FevQ8UZTbfaYdGvCADgjjzRuDhw4oPz8fDU2Np775H9rampSfn6+8vPz3RcMAM5TZGiwpg7pbqq9kVeoFjsD1AEAgG9yOBynbQE+tncX9UuMtiYQgDPiUSkAOE+thxQXV9Xrq90VFqUBAAC4OGv2H9aOkmOm2pwxPSxKA6AtXtu4qaqqkiRFRkZanAQAThiY1EkDkzqaatm5BW2cDQAA4N3m5uw3Had1idSk/vEWpQHQFq9t3LzyyiuSpLS0NIuTAMBJWa2GFC/dUa7y6nqL0gAAALRP4eFafba9zFS7e3S6goIMixIBaEvwuU+5cJMmTTpjfc6cOYqKijrrtQ0NDdq3b5/Ky8tlGIYmT57sjogA0C5Th3TXEx/sUF1TiySp2e7Qm+uK9MDlvS1OBgAAcP5eXpWvU0f1dQgL1owRydYFAtAmtzRuli1bJsMw5HCc/E7gcDiUl5d3Qa/Ts2dPPfLII66OBwDtFh0eohsu66ZF64qctezcQv3HhF78hgoAAPiE4w3Nys4z7445fXiyosNDLEoE4Gzc0riZMGGCDOPkG5jly5fLMAwNHz78rCtuDMNQeHi4unXrpjFjxigrK+ucK3QAwNNmjUw1NW4KDtdq1b5DGts7zsJUAAAA52fxhoOqrm92HhsGW4AD3sxtK25OFRR0YpTOvHnzNGDAAHfcEgA8ZmhKjPolROubsmpn7S9Ld2tkj84Ktnnt6DAAAADZ7Q7NazWUeFK/eKXH8QtzwFt55B3GXXfdpbvuukuxsbGeuB0AuJVhGMrKTDHV1uw/rCc+3GFRIgAAgPOzYk+l9lYcN9XmjGULcMCbuWXFTWvz5s3zxG0AwGOmD0/WP5bvVdmxBmdtbk6++idG69ZWO08BAAB4i9ZbgPeJ76CxvbtYlAbA+WBNPwC0Q3R4iP5xx3CFBpu/jf73O1u1Nv+wRakAAADatreiRsu+qTDVZo9NN80nBeB9aNwAQDsNTY3V/04bZKo1tTj0H6+s08GjdRalAgAAOLP5K/NNx50iQnTzULYAB7ydSxs3NptNNptNwcHBZ6y356P1awGAN7lleLLum9DTVKusadT35q9VbWNzG1cBAAB4VlVdk948ZVdMScrKTFFEqM2iRADOl0sbNw6Hw/nRVr09HwDgzR6+tr8m9u1qqm0vOaZfLNrM9zAAAOAVFq0tVG1ji/PYFmTortHp1gUCcN5cupzlscceu6A6APgDW5Chv8waqmnP5WjfKbs0fLClRP2/iNYPr+xjYToAABDoWuwOzWv1mNQ1lyYoKSbCmkAALgiNGwBwgU4RIXrhrhGa+rccVdeffETq/z7bpT4J0bp2YKKF6QAAQCD7fEeZio6Y5++xBTjgOxhODAAu0rNrB/31tmEKarUxw8/e2KidpcesCQUAAALevJx80/HApI4akRZrTRgAF8zljZt//vOf2rFjh6tfFgB8wsS+XfXL71xiqtU2tuje+Wt1+HijRakAAECg2lFyTKv2HTLV5ozpwRbggA9xeePm/vvv18CBA5WQkKBbbrlFzzzzjDZs2MCATgAB47vjemj6cPPWmkVH6nT/K+vU1GK3KBUAAAhErVfbxHUI0w2Du1kTBkC7uGWvbYfDoYqKCr3zzjt65513JEkdO3bUmDFjNGHCBE2YMEEZGRls9Q3ALxmGoSemDdS+ihqtLzjqrK/Zf1i/fn+bfnfTIOvCAQCAgHH4eKPe2XjQVLt9ZKrCgtkCHPAlLu+czJs3TytWrNCKFSu0a9cuZ72qqkoff/yxPv74Y0lSeHi4Ro4c6WzkjB49WhERTDUH4B/Cgm36x53DNfWvOSqpqnfWX1ldoH6JHXXnqDQL0wEAgECwMLdADc0nV/uG2AzdPirVwkQA2sNwuPEZpoqKCmcTZ8WKFdq0aZNaWlpO3vyU5ypDQkI0bNgwZyNn3Lhx6tixo7uiBZSioiKlpKRIkgoLC5WcnHyOKwC4ypaiKk3/x0rTD03BQYYWfHekRvfqYmEyAADgz5pa7Br/hy9VeuzkL5CmDU3Sn28dYl0oIAC44/23Wxs3rdXU1GjlypXORk5ubq7q609+Izm1kRMUFKRBgwZp4sSJ+vOf/+ypiH6Jxg1grfc2FetHCzeYarGRIXrvB+OU0jnSolQAAMCfnennj/d+MFaXJcdYEwgIED7fuGmtqalJeXl5WrFihb766iutXLlSVVVVpnMMwzCt0sGFo3EDWO9Pn+zU377ca6r1S4jWWw+MUYcw5n0BAADXmvZcjjacMmtveFqs3rp/jHWBgADhjvffLt9V6kKEhIRozJgxevjhh/XBBx+orKxM//jHP9SzZ0+2pwPgVx66up+uuiTeVPumrFo/e32j7HZ23QMAAK6zsfCoqWkjSXPGpluSBcDFs/TXvA0NDVq9erW++uorrVixQqtXr9bx48clie3DAfiVoCBDf751iG75+0rtKqtx1j/dXqanP9+ln03uZ2E6AADgT+bm7Dcdd+sUrmsuTbQoDYCL5dHGTVVVlXJycpyPRq1bt05NTU2STjZqbDabBg0apHHjxmncuHEaP368JyMCgNtEh4foX3eN0NS/5ehobZOz/pcv9qhvYrRuuKy7hekAAIA/KDtWrw82l5hqd45OU4jN0octAFwEtzZuSktLnYOIv/rqK23dutXZoPn2fyMjI5WZmels1IwePVrR0dHujAUAlknrEqXnbhumO1/KVcspj0j9fNEmpXeJ0sCkThamAwAAvu7V1QfUfMrPGOEhQZqVwRbggC9zeeNm3rx5zmbN3r0nB3F+26iJi4vT2LFjnatphg0bpuBgBnMCCBxjesfpsSkD9Oi725y1+ia77nt5rd79wTh1jQ6zMB0AAPBV9U0tenVNgak2bWiSYqNCLUoEwBVc3jG55557ZBiGs1HTq1cv52qacePGqV8/5jgAwJ2j0rSjpFoLc0/+cFVcVa//eGWdXvveSIUF2yxMBwAAfNH7m4p16HijqTZ7TA+L0gBwFbctdQkODtaMGTM0ffp0jRs3Tl27dnXXrQDA5xiGoV/feKn2ltcoN/+ws77uwBH96p2t+sMtl7G7HgAAOG8Oh0Nzc/JNtTG9uqhfImMoAF/n8glVsbGxcjgcam5uVnZ2tqZPn67ExET1799f9957r+bPn296hAoAAlVocJD+fscwJcVEmOpvrC3SvJX51oQCAAA+KXf/YW0vOWaqzRnLahvAH7h8xc2hQ4e0bds250DiFStW6ODBg9q1a5d27dqluXPnSpISEhJMj1ANHTqU3y4DCDhdOoTpX3eN0C1/X6m6phZn/bdLtqt3fAeN78NqRQAAcG6tV9ukdo7UpP7x1oQB4FKG49thNG6Un5/vbOKsWLFCu3btOhng382aDh06aNSoUc6hxaNGjVJ4eLi7owWEoqIipaSkSJIKCwuVnJxscSIArX20pUT3v7reVOsUEaJ3HhyrHnFRFqUCAAC+oPBwrSb+6UudspmUfnXDAH13HCtuAE9zx/tvjzRuWquoqDA1cjZt2iS73X4i0L8bOcHBwRo6dKjGjx+vP/3pT56O6Fdo3AC+4enPd+npz3ebar3jO2jxA2PUMTzEolQAAMDb/c+HO/T8V/ucx1GhNq365ZX8/ABYwG8aN61VV1crJyfH+XjV2rVr1dDQIOlEI6elpeUcr4CzoXED+Aa73aEHX1uvj7aWmuqT+sfrX3eNkC2Ix0kBAIBZbWOzRv3PUh2rb3bWZo9J1+M3XmphKiBwueP9t8uHE7dHdHS0evbsqZ49e6pHjx6Ki4tj3g2AgBMUZOj/Zg7WJd06mupf7CzXnz75xqJUAADAm721/qCpaWMY0t1j0q0LBMDl3LYd+Nk4HA5t3LjR+ajUihUrVFFRcdo5ABBoIkOD9a+7hmvqX3N06Hijs/6P5XvVPzFaNw1NsjAdAADwJg6HQ/Ny9ptqV/SLZz4e4Gc80rhpamrSmjVrnE2alStXqrq62vn11k2aXr16afz48ZowYYImTJjgiYgA4DWSYyP19zuG67Z/rVbzKVMG//OtzeoRF6XBKTHWhQMAAF5jxe5K7a04bqrNGZtuTRgAbuOWxk1NTY1WrlzpHECcl5fnnFkjmRs1hmFo4MCBmjBhgrNZ061bN3fEAgCfkdmjs35700A9sniLs9bYbNd9C9bqvR+MU0JHdt0DACDQzW212qZ3fAeN6x1nURoA7uLyxs2IESNMu0RJ5kbNt7tFfduoGT9+vGJjY10dAwB83qzMVO0sOab5qw44a2XHGnTfgnV6/b5RCg+xWZgOAABYaV9Fjb78xjxuYvaYdGaFAn7I5Y2b9evXm47Dw8OVmZnpfOxp9OjRiorimUsAOB//fcMA7S6v0cq9h5y1TYVH9cvFW/R/MwfzwxkAAAFq/sp803HH8GDdPIxZeIA/cnnjpkOHDho7dqyzUZORkaHQ0FBX3wYAAkKILUh/u22Ypv4tRwWHa531xRsOqn+3aN03oZeF6QAAgBWO1TfpzXVFptqszFRFhlqy9wwAN3P53+yjR48qKMgrdhkHAL8QGxWqF+4eoWl/y9HxxhZn/X8/2qk+8dG6on+8hekAAICnvZFXaPqZIMiQ7hydZmEiAO7k8g4LTRsAcL2+CdF6JmuoTn0yyuGQfrRwg/aU11gXDAAAeFSL3aH5q/JNtWsuTVRybKQ1gQC4HV0WAPARVw1I0M8n9zPVqhua9b2X16qqtsmiVAAAwJOW7ihT4eE6U23O2B4WpQHgCTRuAMCHPHB5L00Z3N1U2195XD9YuF7NLfY2rgIAAP5ibk6+6fjS7h2Vkc4uvYA/o3EDAD7EMAz98ZbLNCipk6m+Ynel/vejnRalAgAAnrCz9JhW7Ttkqs0Z24NdJgE/R+MGAHxMRKhNz981XHEdwkz1F7/erzfWFlqUCgAAuNu8Vqtt4jqEasrgbtaEAeAxNG4AwAd16xShf945XKE287fx/357q9YdOGxRKgAA4C6Hjzfq7Q0HTbXbRqYpLNhmUSIAnkLjBgB81PC0WP1u2kBTrbHFru8vWK/io3VtXAUAAHzRwtwCNTSfnGcXYjN0x8hUCxMB8BQaNwDgw2aOSNF3x5l3kqisadB9C9aqrrHFolQAAMCVmlrsWrDqgKl2/aBuiu8YblEiAJ5E4wYAfNwj1/XX+D5xptrWg8f0izc3yeFwWJQKAAC4gsPh0NOf71LpsXpTnS3AgcBB4wYAfFywLUh/nTVMPeKiTPUlm0v03LK9FqUCAAAXy+Fw6MlPv9HfvjT/93xYaowGp8RYEwqAx9G4AQA/0CkyRP+6a4Siw4JN9T998o0+3VZqUSoAANBeDodDf/j49KaNJP306r4WJAJgFRo3AOAnesd30F9uGyrDMNd/+vpGfVNabU0oAABwwRwOh/7nwx36x/LTmzb/e/Mgje/T1YJUAKxC4wYA/MgV/eL1yHX9TbXjjS269+U8HTneaFEqAABwvhwOh367ZIf+tWK/qW4Y0h9vuUyzMtlJCgg0NG4AwM98b3xP3Tw0yVQrPFynB15dr6YWextXAQAAqzkcDv36/e16Kef0ps2fpg/WzIwUi5IBsBKNGwDwM4Zh6H9uHnTa0MJV+w7pt0u2WxMKAACcld3u0KPvbtO8lfmmepAhPTVzsKYPT7YmGADL0bgBAD8UHmLT83cOV0LHMFP95VUH9OqaAxalAgAAZ2K3O/Tf727VgtXm/0YHGdKfbx2iaUNp2gCBjMYNAPiphI7hev7OEQoNNn+rf+zdbVqz75BFqQAAwKnsdod++fYWvbamwFS3BRl6Jmuopg5JauNKAIGCxg0A+LHBKTH64y2XmWrNdofuf3W9Cg/XWpQKAABIUovdoYff2qzsvEJTPTjI0LOzhmrK4O4WJQPgTWjcAICfu2lokv5jYi9T7fDxRn3v5bU63tBsUSoAAAJbi92hX7y5SYvWFZnqwUGG/nrbMH1nUDeLkgHwNjRuACAA/OKafprUP95U21larZ+9sVF2u8OiVAAABKYWu0M/X7RJi9cfNNVDbIaeu32Yrh2YaFEyAN6Ixg0ABIATz8kPUe/4Dqb6J9vK9MzS3RalAgAg8DS32PXT1zfq7Q3mpk2oLUj/uGO4Jl9K0waAGY0bAAgQ0eEheuGuEeoUEWKqP7N0tz7cUmJRKgAAAkdTi10/fn2j3ttUbKqHBgfpn3cO15WXJFiUDIA3o3EDAAEkPS5Kf7ttmGxBhqn+0BubtK24yqJUAAD4v6YWu360cIM+2Gz+ZUlocJD+ddcIXdHqkWYA+BaNGwAIMOP6xOm/r7/EVKtratF9L69TZU2DRakAAPBfjc12/eC19fpoa6mpHhYcpBfvHqGJfbtalAyAL6BxAwABaPaYdN06IsVUO3i0Tve/sk6NzXaLUgEA4H8amlv0wKvr9cm2MlM9PCRIc2dnaHwfmjYAzo7GDQAEIMMw9JubLtWItFhTPS//iB59d6scDnaaAgDgYjU0t+j+V9br8x3mpk1EiE1zZ2dqTO84i5IB8CU0bgAgQIUF2/T3O4are6dwUz07r1AvrzpgUSoAAPxDfVOLvr9gnb7YWW6qR4baNG9Ohkb36mJRMgC+hsYNAASwrtFhev6uEQoPMf/n4DdLtitnT6VFqQAA8G31TS26b8E6LfumwlSPCrVp/j2ZGtmTpg2A80fjBgAC3MCkTvq/GUNMtRa7Qw+8ul4HDh23JhQAAD6qrrFF985fq692mZs2HcKC9fJ3M5WR3tmiZAB8FY0bAICuv6ybfjSpt6lWVdeke+evVXV9k0WpAADwLbWNzfru/Dx93WrVavS/mzbD02jaAP+/vfuOr6q+/zj+vtmLJEAIe4fIlJEAoUgBd0VE/YmAbIFQLU7UOovWoi2Ie5SNoAJVqohonYAggRAIS7ashJkwEsge5/cHzS2HDBJIcu54PR+PPHr5nHPP93PtN+fmvu8ZqDiCGwCAJOnRGyN1c9u6ptrek+f12OLNKizkYsUAAJQlMzdf98/boLW/nTLVg/289NHY7urSpGYpzwSAshHcAAAkSR4eNr0xqJNa16thqv+w86Smfb/boq4AAHB853PyNWrOBq3bf9pUD/H31sdjY9Sxcag1jQFwCQQ3AAC7QF8vzRwRrZoB3qb6eyt+09LNRyzqCgAAx3UuO0+j5sQr/qA5tAkN8NbHY7urQ6MQizoD4CoIbgAAJo1rBej9oVHy8rCZ6k99tlXbktMs6goAAMeTnp2nkXPilXDojKleM8Bbn4yNUfuGhDYArh7BDQCgmB4ta+vFO9qZajn5hRo3P0Enz2Vb1BUAAI4jLStPI2bHa9Phs6Z67UAfLYyNUdsGwdY0BsDlENwAAEo0LKaphsU0MdWOp2dr/IKNyskvsKgrAACsl5aZp+Gz12tz0llTPSzoQmjTuh6hDYDKQ3ADACjVpP7tFNPCfOvSxMNn9dzn22UY3GkKAOB+zmbmaujsddp6yenDYUG+WjguRpF1a5TyTAC4MgQ3AIBSeXt66P2hUWpU099U/2xjsmavOWBRVwAAWONMRq7um7le24+km+rhNXy1KDZGrQhtAFQBghsAQJlqBfpo1shoBfh4muqvfL1Tq/akWNQVAADV69T5HA2ZuU47jplDm7rBF0KbiPAgizoD4OoIbgAAl9W6XrDeGNTJVCs0pAmfbNL+lPPWNAUAQDVJPZ+j+2au167j50z1+iF+WhzbQy3qENoAqDoENwCAcrmlXT1NvCnSVDuXna+x8xOUlpVnUVcAAFStlHM5GjJjnXafMIc2DUL8tCg2Rs3CAi3qDIC7ILgBAJTbhOsj1K9DfVNtf0qGHl6YqIJCLlYMAHAtJ9OzNXhGnPaeNB9d2jDUX4vH91DT2oQ2AKoewQ0AoNxsNpumDrxW7RqYb3O6ak+K/vGfXRZ1BQBA5TuRnq3BM9bpt5QMU71xLX8tHh+jxrUCLOoMgLshuAEAVEiAj5dmjIhWWJCPqT7j5/1asjHZoq4AAKg8x9MuhDb7U82hTZNaAVoU20ONahLaAKg+BDcAgAprGOqvfw6LkrenzVR/5t/btOnwGYu6AgDg6h09m6VBM+J04JLQplntAC0eH6OGof4WdQbAXRHcAACuSHSzWpp8ZwdTLbegUOMXbNTxtGyLugIA4Moln8nUoBlxOnQq01RvERaoxeN7qH4IoQ2A6kdwAwC4Yvd2bazRPZuZainnchS7IEHZeQXWNAUAwBVIOp2pwTPWKel0lqnesk6gFsXGqG6wn0WdAXB3BDcAgKvy3G1tdF1EmKm2NTlNf16yVYbBnaYAAI7v8KkLoU3yGXNo0yo8SAtjYxROaAPAQgQ3AICr4uXpoXfv66xmtc0Xaly6+aj+uWq/RV0BAFA+B1MzNHhGnI6cNYc219StcSG0qUFoA8BaBDcAgKsWGuCjWSOjFeTrZapP+XaXftx5wqKuAAAo24HUDA2esU5HL7k2W+t6NfTJuO4KC/K1qDMA+B+CGwBApYgIr6G3h3SS7aIbTRmG9Miizdp74px1jQEAUILfUs5r0PQ4HU83hzZt6wfrk3Exqk1oA8BBENxIOnTokCZOnKjWrVsrMDBQtWrVUteuXTV16lRlZmZefgNlmDdvnmw2W7l+5s2bVzkvCAAscn3ruvrzra1NtfM5+Ro7P0FnM3Mt6goAALN9J89p8Ix1Onkux1Rv3zBYn4zrrlqBPhZ1BgDFuX1ws2zZMl177bV6/fXXtXv3bmVmZurMmTNKSEjQU089pc6dO2vfvn1WtwkATmP871vozk4NTLVDpzL1p082Kb+g0KKuAAC4YM+Jcxo8Y71SLgltrm0Uoo/HxCg0gNAGgGPxuvwqrisxMVGDBg1SVlaWgoKC9Mwzz6hv377KysrSokWLNHPmTO3Zs0f9+vVTQkKCatSocVXjffvtt2rQoEGpyxs1anRV2wcAR2Cz2fT3/7tWB1IztCU5zV7/Zd8p/W35Tr14RzsLuwMAuLNdx9M1dOZ6ncowHwXasXGo5t/fTSH+3hZ1BgClc+vg5pFHHlFWVpa8vLz03XffqUePHvZl119/vVq1aqWnnnpKe/bs0bRp0/Tiiy9e1XiRkZFq1qzZ1TUNAE7Az9tT04dH645315gOQ5+39qBa16uhwd2aWNgdAMAd7TiarmGz1+v0JaFN5yah+vD+bgr2I7QB4Jjc9lSp+Ph4rV69WpI0ZswYU2hTZOLEiWrTpo0k6a233lJeXl619ggAzqxeiJ+mD4+Sj5f5reaFpdu14eBpi7oCALij7UfSdN+sdcVCm6imNTWf0AaAg3Pb4OaLL76wPx49enSJ63h4eGjEiBGSpLNnz2rFihXV0RoAuIzOTWrq73d3MNXyCgz9ccFGHTmbZVFXAAB3si05TUNnrdfZTPOXsF2b1dSH93dTDUIbAA7ObYObNWvWSJICAwMVFRVV6nq9e/e2P/7ll1+qvC8AcDV3d2mk8b9vYaqdysjVuA8TlJmbb1FXAAB3sCXprIbOWqe0LHNo0615Lc0b3U1Bvm595QgATsJt91Q7d+6UJEVERMjLq/T/DK1b/++2tkXPuVKjR4/W7t27lZqaquDgYEVEROjGG2/UAw88oIYNG17xdpOTk8tcfuzYsSveNgBUhqduba3dJ85p5e4Ue23HsXQ98ekWvXdfF9lsNgu7AwC4osTDZzRiTrzOZZu/JOjRorZmj4pWgI/bfhQC4GTccm+VnZ2t1NRUSZe/k1PNmjUVGBiojIwMJSUlXdW4K1eutD8+deqUTp06pfXr12vatGl68803NX78+CvabuPGja+qLwCoap4eNr09pLPufO8X7U/JsNe/3nZc7/y0Tw/f0MrC7gAArmbjoTMaNSde53LMoc11EWGaOSJa/j6eFnUGABXnlqdKnTt3zv44KCjosusHBgZKks6fP39F47Vo0UJPPPGElixZovj4eMXHx2vRokUaOHCgbDabsrOz9cc//lEzZsy4ou0DgDMI9vPWrBHRCvYzf2fw+vd79J/txy3qCgDgahIOntaI2euLhTa9WoVp1khCGwDOx2YYhmF1E9UtKSlJTZpcuBXt8OHDNX/+/DLXb9KkiZKSktSyZUvt27evQmOlpaUpODi41NMAvvrqK919993Ky8tTQECAfvvtN9WrV69CY5TnVKlu3bpJuvDaL3eUEQBUpZ/3pGjU3HgVXvTuE+DjqSUP/E5t6gdb1xgAwOnFHzitUXPjlZlbYKr3jqyj6cOj5OdNaAOgaiUnJ9vPiqmsz99uecSNn5+f/XFubm4Za16Qk5MjSfL396/wWCEhIWVeu+H222/XX/7yF0lSZmamZs+eXeExGjVqVOZP/fr1K7xNAKgqv4+so+f6tTXVMnMLNPbDBJ06n2NRVwAAZxf32ymNnFM8tLm+dTihDQCn5pbBTY0aNeyPy3P6U0bGhesxlOe0qisRGxtrD3dWrVpVJWMAgCO5v2czDYwyf/tw5GyWHvh4k3LzCy3qCgDgrNbuS9XoefHKyjOHNje2CdcHw7oQ2gBwam4Z3Pj5+al27dqSLn+a0ZkzZ+zBTVVdBDg8PNzez5EjR6pkDABwJDabTX+7q726NAk11eMPnNZLy361pikAgFNaszdVo+dtUHaeOfi/uW1dvT80Sr5ehDYAnJtbBjeS1LbthcP09+3bp/z8/FLX27Vrl/1xmzZtqqwfboULwN34ennqn8OjVD/Ez1T/eP1hLVh3yKKuAADO5Oc9KRrz4QblXHK05h/a19N7Q7vIx8ttP+4AcCFuuye77rrrJF04DWrjxo2lrnfxqUs9e/askl5SUlLstydv0KBBlYwBAI4ovIafZo6Ilp+3+e3opS9/1drfUi3qCgDgDFbsPqmx8xOKhTb9OtTX20M6y9vTbT/qAHAxbrs3u/POO+2P586dW+I6hYWF9jtOhYaGqm/fvlXSy4wZM1R0c6/evXtXyRgA4KjaNwzR1Hs6mmr5hYb+9PEmHT6VaVFXAABH9uPOExo/f2Ox66L179hAbw3uRGgDwKW47R6tW7du6tWrlyRp9uzZiouLK7bOtGnTtHPnTknSI488Im9vb9PylStXymazyWazadSoUcWef/DgQSUmJpbZx1dffaW//vWvki7ctWr06NFX8nIAwKn179hAE/pGmGpnMvM0bn6CzueUfjorAMD9fL/jhP740UblFphDmwGdGuiNezvKi9AGgIvxsroBK7311lvq2bOnsrKydPPNN+vZZ59V3759lZWVpUWLFmnGjBmSpMjISE2cOLHC2z948KD69u2rHj16qH///urYsaPCw8MlSfv379dnn32mzz77zH60zWuvvaaGDRtW3gsEACfy+E2R2n3inL7fccJe233inB5bvFnTh0XJw4NrgQGAu/vP9uN6aOEm5RUYpvrdnRtq6sCO8uS9AoALcuvgpnPnzlq8eLGGDRum9PR0Pfvss8XWiYyM1PLly023EK+ouLi4Eo/oKRIQEKA33nhDsbGxVzwGADg7Dw+b3hjUSXe//4v2nDhvr3+/44Te+GGPJt58jYXdAQCs9s22Y3poYaLyC82hzT1RjfSP/7uW0AaAy3Lr4EaS+vfvr61bt+qtt97S8uXLlZycLB8fH0VERGjgwIGaMGGCAgICrmjbUVFR+uijjxQXF6eEhAQdO3ZMqampys/PV82aNdWuXTvdcMMNGjt2rP1IHABwZ0G+Xpo1oqvueG+Nzmbm2evv/LRPkXVrqH9HLuAOAO7oq61H9ciizSq4JLQZFN1Yr97dgaMyAbg0m1F0ng5cVnJysho3bixJSkpKUqNGjSzuCADKtva3VA2fHW/6A93P20Of/fF3at8wxMLOAADV7cstR/XY4uKhzZBuTTT5zvaENgAcSlV8/ubKXQAAh/O7lmF6sX9bUy07r1Dj5ico5VyORV0BAKrbF4lH9OiixGKhzbAYQhsA7oPgBgDgkIbFNNV93ZuYasfSsvXHjzYqJ7/Aoq4AANVlycZkPfavzboks9HIHk318gBCGwDug+AGAOCQbDabXuzfTt2a1zLVNx46o+c/3y7O9AUA1/WvhCQ98dkWXbqrH92zmV68o51sNkIbAO6D4AYA4LB8vDz0wdAuahjqb6p/ujFZc385aE1TAIAqtSj+sP68ZGux0Gbsdc31l9vbEtoAcDsENwAAh1Y7yFezRkYrwMfTVP/b8h36eU+KRV0BAKrCx+sP6el/bysW2ozv3ULP9WtDaAPALRHcAAAcXpv6wXr93o6mWqEhTfhkkw6kZljUFQCgMi2IO6jnPt9erP5gn5Z6+tbWhDYA3BbBDQDAKdzavr4euzHSVEvPztfYDzcoPTvPoq4AAJXhw7UH9cLSX4vVH7o+Qk/ecg2hDQC3RnADAHAaD10fods61DPVfkvJ0CMLi98qFgDgHGavOaBJXxYPbR69sZUm3kxoAwAENwAAp+HhYdNrAzuqTf1gU33F7hRN+XaXRV0BAK7UzJ/36+WvdhSrP35TpB695ChLAHBXBDcAAKcS4OOlmSOiVDvQx1Sfvmq/Pk9MtqgrAEBF/XPVb5r89c5i9SdvuUYP39DKgo4AwDER3AAAnE6jmgH65/AoeXuaD5//85Jt2px01pqmAADl9t6Kffr7N8WPlPzzra31p74RFnQEAI6L4AYA4JS6Nqullwe0N9Vy8wsVOz9BJ9KzLeoKAHA5b/+4V1O/3V2s/txtbfRAn5YWdAQAjo3gBgDgtAZ3a6JRv2tmqp08l6PY+QnKziuwpikAQKne/GGPXv9+T7H68/3aaNzvW1jQEQA4PoIbAIBTe75fG/WMqG2qbUlO0zP/3ibD4E5TAOAIDMPQ69/t1ps/7C227MX+bTW2F6ENAJSG4AYA4NS8PD307pAualo7wFT/PPGIZvy836KuAABFDMPQa9/t1ts/7Su27OUB7TSqZ3MLugIA50FwAwBwejUDfTRzRLSCfL1M9b//Z5dW7DppUVcAAMMw9Pf/7NJ7K34rtmzyXe01vEez6m8KAJwMwQ0AwCVE1q2hNwd1ku2iG00ZhvTwwkTtO3nOusYAwE0ZhqFXvt6p6auKH/346t0dNLR7Uwu6AgDnQ3ADAHAZN7atqydvucZUO5eTr7EfJigtM8+irgDA/RiGoZe/2qmZqw+Y6jabNOX/rtWQbk0s6gwAnA/BDQDApTzQu6Xu6NjAVDt4KlMTFm5SfkGhRV0BgPswDEMvLduhOb8UD22m3tNR93ZtbFFnAOCcCG4AAC7FZrNpyj3XqkPDEFN99d5UvfL1Lou6AgD3UFho6C9Lf9W8tQdNdQ+b9Pq9HXVPVCNrGgMAJ0ZwAwBwOX7enpoxIkphQb6m+pxfDuhfG5Is6goAXFthoaHnl27XgnWHTHUPm/TGoE66qzOhDQBcCYIbAIBLqh/ir+nDo+TjaX6re+6LbUo4eNqirgDANRUWGnr28236ZP1hU93Tw6a3h3TWgE4NLeoMAJwfwQ0AwGVFNa2pV+7uYKrlFRj640cbdeRslkVdAYBrKSg09OclW7XokiMavTxsemdIZ91+bYNSngkAKA+CGwCAS7snqpHGXtfcVEs9n6vY+QnKyi2wqCsAcA0FhYae/GyLPt2YbKp7edj07n1ddFuH+hZ1BgCug+AGAODynv5Da/0+so6p9uvRdD3x2RYZhmFRVwDg3PILCjXxX5v1701HTHVvT5veH9pFt7avZ1FnAOBaCG4AAC7Py9ND7wzprBZhgab68q3H9N6KfRZ1BQDOK7+gUI/9a4u+2HzUVPfx9NA/h0Xp5naENgBQWQhuAABuIcTfWzNHRquGn5ep/tp3e/Tdr8ct6goAnE9eQaEeWbxZy7ZcEtp4eWj68Cjd0KauRZ0BgGsiuAEAuI2WdYL09pDO8rCZ648t3qxdx9OtaQoAnEheQaEeXpio5VuPmeo+Xh6aOSJafVuHW9QZALgughsAgFvpe024nvlDG1MtI7dA4+Yn6HRGrkVdAYDjy80v1IRPNumb7eajFH29PDRnZFf1vuRaYgCAykFwAwBwO2N7NdfdXRqaakmns/TgxxuVV1BoUVcA4Lhy8gv04Meb9O2vJ0x1P28PzR3VVde1CrOoMwBwfQQ3AAC3Y7PZ9MpdHdSpcaipvm7/af112Q5rmgIAB5WTX6AHPtqkH3aaQxt/b0/NHdVNv4sgtAGAqkRwAwBwS37enpoxPEp1g31N9QXrDumjdYcs6goAHEt2XoHGL9ion3adNNUDfDw1b3RX9WhZ26LOAMB9ENwAANxWeLCfZgyPlq+X+e3wxS9/1br9pyzqCgAcQ3behet/rdydYqoH+nhq/v3d1L0FoQ0AVAeCGwCAW+vYOFRT7rnWVMsvNPTARxuVdDrToq4AwFpZuQUa+2GCVu9NNdWDfL00f0w3RTerZVFnAOB+CG4AAG5vQKeGeqBPS1PtTGaexs1PUEZOvkVdAYA1MnPzNebDDVqzzxza1PD10oIx3RTVlNAGAKoTwQ0AAJKeuPka3dA63FTbdfycHv/XZhUWGhZ1BQDVKyMnX/fP26C1v5lPFw3289JHY7urc5OaFnUGAO6L4AYAAEmeHja9ObiTIsKDTPVvfz2hN3/ca1FXAFB9zufka/TcDVq3/7SpHuLvrY/HxqjjJXfiAwBUD4IbAAD+q4aft2aNiFaIv7ep/vaPe7V86zGLugKAqncuO0+j5sQr/qA5tAkN8NbHY7urQ6MQizoDABDcAABwkWZhgXp/aBd5ethM9Ymfbtb2I2kWdQUAVSc9O08j58Qr4dAZU71mgLc+GRuj9g0JbQDASgQ3AABcomdEmF7o18ZUy84rVOz8BKWcy7GoKwCofGlZeRo+O16bDp811WsH+mhhbIzaNgi2pjEAgB3BDQAAJRj5u2Ya3LWxqXY0LVsPfLRRufmFFnUFAJUnLTNPw2ev15aks6Z6WNCF0KZ1PUIbAHAEBDcAAJTAZrPprwPaq2sz8x1UEg6d0QtfbJdhcKcpAM7rbGauhs5ep63J5lNA69Tw1aLYGEXWrWFRZwCASxHcAABQCh8vD30wLEoNQvxM9cUJSfpw7UFrmgKAq3QmI1f3zVyv7UfSTfXw/4Y2EeGENgDgSAhuAAAoQ1iQr2aOjJa/t6ep/vLynVqzN9WirgDgypw6n6MhM9dpxzFzaFM3+EJo07JOkEWdAQBKQ3ADAMBltGsQotcGdjTVCgoN/emTTTqYmmFRVwBQMannc3TfzPXadfycqV4/xE+LY3uoBaENADgkghsAAMqh37X19fANrUy1tKw8jZ2foHPZeRZ1BQDlk3IuR0NmrNPuE+bQpmGovxbH9lCzsECLOgMAXA7BDQAA5fToDa10S7u6ptq+k+f1yKLNKijkYsUAHNPJ9GwNnhGnvSfPm+oNQ/21KDZGTWoHWNQZAKA8CG4AACgnDw+bXr+3k1rXM1+486ddJ/Xad7st6goASnciPVuDZ6zTbynm0zob1/LX4vExalyL0AYAHB3BDQAAFRDo66WZI6JVK9DHVP9g5W9auvmIRV0BQHHH0y6ENvsvuRZX09oBWhTbQ41qEtoAgDMguAEAoIIa1wrQ+0O7yMvDZqo/9dlWbUk6a01TAHCRo2ezNGhGnA5cEto0DwvUotgYNQz1t6gzAEBFEdwAAHAFYlrU1ksD2plqOfmFil2QoJPp2RZ1BQBS8plMDZoRp0OnMk31Fv8NbeqHENoAgDMhuAEA4AoN7d5Uw2Oammon0nMUu2CjsvMKLOoKgDtLOp2pwTPWKel0lqness6F0KZusJ9FnQEArhTBDQAAV+Ev/dsqpkUtU21z0lk9++9tMgzuNAWg+hw+dSG0ST5jDm1ahQdpYWyMwgltAMApEdwAAHAVvD099P7QKDWuZT714N+JRzRr9QGLugLgbg6mZmjQjDgdOWsOba6pW+NCaFOD0AYAnBXBDQAAV6lWoI9mjeiqQB9PU/3Vb3Zqxe6TFnUFwF0cSM3Q4BnrdCzNfH2t1vVq6JNx3RUW5GtRZwCAykBwAwBAJbimXg29MaiTqVZoSA9/kqh9J89b0xQAl/dbynkNmh6n45dcFL1t/WB9Mi5GtQltAMDpEdwAAFBJbm5XT0/cHGmqncvJV+z8BKVl5lnUFQBXte/kOQ2esU4nz+WY6u0bBuuTcd1VK9DHos4AAJWJ4AYAgEr0p74Ruv3a+qba/tQMPbQoUfkFhRZ1BcDV7DlxIbRJuSS0ubZRiD4eE6PQAEIbAHAVBDcAAFQim82mqfd0VLsGwab6z3tS9PdvdlnUFQBXsut4uobMWKfU87mmesfGoVowprtCArwt6gwAUBUIbgAAqGT+Pp6aOSJaYUHmb7xnrTmgTxOSLOoKgCvYcTRd981cr1MZ5tCmc5NQLRjTTSH+hDYA4GoIbgAAqAINQv01fXiUvD1tpvpzn2/XxkNnLOoKgDPbfiRN981ap9OXhDZRTWtq/v3dFOxHaAMArojgBgCAKhLVtJYm39nBVMstKNT4BRt1LC3Loq4AOKNtyWkaOmu9zl5yofOuzWrqw/u7qQahDQC4LIIbAACq0L1dG+v+ns1NtdTzOYqdv1FZuQUWdQXAmWxJOquhs9YpLcsc2nRvXkvzRndTkK+XRZ0BAKoDwQ0AAFXs2dtaq1erMFNt25E0PbVkqwzDsKgrAM4g8fAZDZu9XunZ+aZ6jxa1NXd0VwUS2gCAyyO4AQCginl5eujdIV3UrHaAqb5sy1G9v/I3i7oC4Og2Hjqj4bPjde6S0Oa6iDDNGdVVAT6ENgDgDghuAACoBiEB3po1Mlo1Lvl2/LXvduv7HScs6gqAo0o4eFojZq/X+RxzaNOrVZhmjYyWv4+nRZ0BAKobwQ0AANUkIryG3h7SWbaLbjRlGNKjixK158Q56xoD4FDW7z+lEXPilXHJdbB6R9bRzBHR8vMmtAEAd0JwAwBANerbOlxP39raVMvILdDYDxN05pJb/AJwP3G/ndKouRuUeUloc33rcM0YEUVoAwBuiOAGAIBqFvv7Frqrc0NT7fDpTD348SblFRRa1BUAq63dl6rR8+KVlWcObW5sE64PhnWRrxehDQC4I4IbAACqmc1m06t3d1DHxqGmetz+U/rbVzusaQqApdbsTdXoeRuUnWcOb29uW1fvD40itAEAN0ZwAwCABfy8PTVjeJTCa/ia6h/GHdIn6w9b1BUAK6zak6IxH25QTr45tPlD+3p6b2gX+XjxJzsAuDPeBQAAsEjdYD/NGBFd7EPZX5Zu1/r9pyzqCkB1WrH7pMbNTygW2vTrUF9vD+ksb0/+XAcAd8c7AQAAFurUOFT/+L8Oplp+oaEHPt6k5DOZFnUFoDr8uPOExs/fqNxLQpv+HRvorcGdCG0AAJIIbgAAsNxdnRtpfO8WptrpjFyN/TBBGTn5FnUFoCp9v+OE/vjRRuVeckHyOzs10Bv3dpQXoQ0A4L94RwAAwAE8dUtr9b2mjqm26/g5PfHpFhUWGhZ1BaAq/Gf7cT3w0UblFZh/t+/u0lDT7u1EaAMAMOFdAQAAB+DpYdNbQzqrZZ1AU/2b7cf19k97LeoKQGX7ZtsxTfhkk/IvCWTviWqkqfd0lKeHzaLOAACOiuAGAAAHEeznrVkjuyrYz8tUf/OHvfpm2zGLugJQWb7aelQTFiYWC20GRTfWlP+7ltAGAFAighsAABxI87BAvTe0iy79/Pb4v7Zox9F0a5oCcNWWbj6ihxcmquCS0GZItyZ69e4O8iC0AQCUguAGAAAH06tVHT3fr62plpVXoHHzE5R6PseirgBcqc8Tk/XY4s269HJVw2KaaPKd7QltAABlIrgBAMABje7ZTPdGNzLVjpzN0oMfbSp262AAjmvJxmQ9/q8txUKbkT2a6uUBhDYAgMsjuAEAwAHZbDa9fGd7RTWtaarHHzytSV9ul2FwpynA0f0rIUlPfLZFl/66ju7ZTC/e0U42G6ENAODyCG4AAHBQvl6e+uewKNUP8TPVF8YnacG6QxZ1BaA8FsUf1lOfbS0W2ozr1Vx/ub0toQ0AoNwIbgAAcGB1avhq5oho+Xmb37JfWrZDa/elWtQVgLJ8vP6Qnv73tmL18b1b6Nnb2hDaAAAqhOAGAAAH175hiF4b2NFUKyg09OAnm3ToVIZFXQEoyYK4g3ru8+3F6g/2aamnb21NaAMAqDCCGwAAnMDt1zbQQ9dHmGpnM/M09sMEncvOs6grABeb98sBvbD012L1h66P0JO3XENoAwC4IgQ3AAA4icdujNRNbeuaantPnr9wm+FLb1kDoFrNXnNALy7bUaz+6I2tNPFmQhsAwJUjuAEAwEl4eNj0xqBOuqZuDVP9h50nNe373RZ1BWDmz/v18lfFQ5vHb4rUozdGWtARAMCVENwAAOBEgny9NGtktGoGeJvq7634TUs3H7GoK8B9/XPVb5r89c5i9SdvuUYP39DKgo4AAK6G4AYAACfTuFaA3h8aJS8P86kXT322VduS0yzqCnA/763Yp79/s6tY/ek/tNaf+kaU8AwAACqO4AYAACfUo2VtTbqjnamWk1+ocfMTdPJctkVdAe7j7R/3auq3xU9RfO62Nvpj75YWdAQAcFUENwAAOKnhMU01tHsTU+14erbGL9ionPwCi7oCXJthGHrj+z16/fs9xZY936+Nxv2+hQVdAQBcGcENAABObFL/durevJaplnj4rJ77fLsMgztNAZXJMAy9/v0evfXj3mLLXuzfVmN7EdoAACofwQ0AAE7Mx8tD7w/tokY1/U31zzYma/aaAxZ1BbgewzA09dvdeuenfcWWvTygnUb1bG5BVwAAd0BwAwCAk6sd5KuZI6IV4ONpqr/y9U6t2pNiUVeA6zAMQ3//zy69v/K3Yssm39Vew3s0q/6mAABug+AGAAAX0KZ+sF6/t5OpVmhID32ySftTzlvTFOACDMPQK1/v1PRV+011m036+90dNLR7U4s6AwC4C4IbAABcxK3t6+nxmyJNtfTsfI2dn6D07DyLugKcl2EY+utXOzRztfm0Q5tN+sf/XavB3ZqU8kwAACoPwQ0AAC7koesj1K9DfVNtf0qGHl6YqIJCLlYMlJdhGHpp2Q7N/eWgqW6zSVPv6ah7oxtb0xgAwO0Q3AAA4EJsNpumDrxWbesHm+ord6doyn92WdQV4FwKCw29sHS75q09aKp72KTX7+2oe6IaWdMYAMAtEdwAAOBiAny8NHNktGoH+pjq03/er1mr9+tAaoZy8gss6g5wbIWFhp77Yrs+WnfYVPewSW8M6qS7OhPaAACql5fVDQAAgMrXMNRf/xwepftmrlNewf9Okfrb8p362/KdkqS6wb5qVDNAjWr6//cnwP6/DUL95OvlWdrmAZdUWGjo2c+3adGGJFPd08OmtwZ30u3XNrCoMwCAOyO4AQDARXVtVkt/u7O9/rxkW4nLT6Tn6ER6jjYeOlPicoIduJOCQkNPL9mqTzcmm+peHja9PaSzbrvk2lEAAFQXghsAAFzYoK5NtPPYuWLX6igPgh24i4JCQ09+tkX/3nTEVPfysOnd+7ro1vb1LOoMAACCGwAAXN4Lt7dV7UAffbvjuJJOZyktq3JuDU6wA1eQX1CoJz7doi82HzXVvT1ten9olG5qW9eizgAAuIDgBgAAF+fpYdNDN7TSQze0kiSlZ+fpyJksJZ/JUvKZzEv+t3qCHZtNCq9BsANr5RcU6rF/bdGyLebQxsfTQx8M66Ib2hDaAACsR3ADAICbCfbzVnB9b7W55JbhRaoj2DEMgh1YK6+gUI8u2qzl246Z6j5eHpo+LEp9W4db1BkAAGYENwAAwMRZgp26NfxKDHUa1fRXfYIdlCGvoFAPL0zUN9uPm+o+Xh6aOSJavSPrWNQZAADFEdwAAIAKcZRg53h6to6nZyuBYAcVkJtfqAmfbNJ3O06Y6r5eHpo9squuaxVmUWcAAJSM4AYAAFQqgh04qpz8Av3p40T9sNMc2vh5e2jOyK76XQShDQDA8RDcAACAanW5YCctqyjY+V+Yc3HAk56df9U9EOy4n+y8Aj348Sb9tOukqe7v7ak5o7qqR8vaFnUGAEDZCG4AAIBDCfH3Voi/t9o2INhB5cjOK9D4BRu1ak+KqR7g46l5o7upW/NaFnUGAMDlEdwAAACn4grBToNQf/l4eVx1H7i87LwCjZufoNV7U031QB9PfXh/N0U3I7QBADg2ghsAAOBSCHZQJCv3QmizZp85tAny9dKH93dVVFNCGwCA4yO4AQAAbsVZgp16wX6XhDoXnYoVQrBzOZm5+RozL0Fx+0+Z6jV8vTR/TDd1blLTos4AAKgYghsAAICLOEqwcywtW8fSsrXhIMFORWXk5Ov+eRu0/sBpUz3Yz0sLxnRXx8ah1jQGAMAVILgBAACogIoEO0mXBjynM3Uuh2CnKp3Pydf9czco/qA5tAnx99ZHY7qrQ6MQizoDAODKENwAAABUovIEOyUfrUOwc7XOZedp9NwNxU4/Cw24ENq0b0hoAwBwPgQ3AAAA1ehCsBOidg1KDhEIdq5MenaeRs6JV+Lhs6Z6zQBvfTw2ptQgDQAAR0dwAwAA4EAIdiouLStPI+bEa0vSWVO9dqCPPh7XXa3rEdoAAJwXwQ0AAIATIdgxS8vM0/A567U1Oc1UDwvy0SfjYhRZt0aljAMAgFUIbgAAAFyIOwU7ZzNzNWz2em0/km6q16nhq4XjuisinNAGAOD8CG4AAADciDMEOx72YKd4qNOoZoDqhfgpIydfQ2et145j5tAmvIavFsbGqGWdoKvuEwAAR0BwAwAAALuygh3DMJSela8ke5hTPOA5XwnBTqEhHU3L1tG0bMUfLL7cwyb5eXsqM7fAVK8b7KuF42LUgtAGAOBCCG4AAABQLjabTSEB3goJCCnx1trVGexcGtrUD/HTwnExahYWeNXbBwDAkRDcAAAAoFJYFew0DPXXwnExalI7oDJeBgAADoXgRtKhQ4f09ttva/ny5UpKSpKvr69atmype++9V3/6058UEFA5fwR88803mjFjhjZs2KCUlBTVqVNHXbt2VWxsrP7whz9UyhgAAACOqiqCnaa1A/TRmO5qXIvQBgDgmmyGYRhWN2GlZcuWadiwYUpPTy9xeWRkpJYvX66IiIgrHqOwsFCxsbGaPXt2qeuMHTtW06dPl4dH5dwa82LJyclq3LixJCkpKUmNGjWq9DEAAACqmjnYyZRhSL2vqaMAH76LBAA4hqr4/F35KYETSUxM1KBBg5Senq6goCBNnjxZa9eu1Y8//qhx48ZJkvbs2aN+/frp3LlzVzzOc889Zw9tOnfurIULFyo+Pl4LFy5U586dJUmzZs3S888/f/UvCgAAwEUVHbHTvmGIbm1fX3/oUJ/QBgDg8tz6iJvf//73Wr16tby8vPTzzz+rR48epuVTp07VU089JUmaNGmSXnzxxQqPsWfPHrVr1075+fmKjo7Wzz//LH9/f/vyzMxM9e7dWwkJCfLy8tLOnTuv6uieknDEDQAAAAAAVY8jbipRfHy8Vq9eLUkaM2ZMsdBGkiZOnKg2bdpIkt566y3l5eVVeJw333xT+fkXzsV+5513TKGNJAUEBOidd96RJOXn5+uNN96o8BgAAAAAAMA1uW1w88UXX9gfjx49usR1PDw8NGLECEnS2bNntWLFigqNYRiGli5dKklq3bq1YmJiSlwvJiZG11xzjSRp6dKlcuODoAAAAAAAwEXcNrhZs2aNJCkwMFBRUVGlrte7d2/7419++aVCYxw4cEBHjx4ttp2yxjly5IgOHjxYoXEAAAAAAIBrctvgZufOnZKkiIgIeXmVflG71q1bF3tOee3YsaPE7VT2OAAAAAAAwDW55WX4s7OzlZqaKkmXvVBQzZo1FRgYqIyMDCUlJVVonOTkZPvjy41TdPEiSVc1TkmOHTtWoe0BAAAAAADH4JbBzcW39g4KCrrs+kXBzfnz56tsnMDAQPvjio5zcehTnp7S09MrtH0AAAAAAHB5F+cAlcUtg5vs7Gz7Yx8fn8uu7+vrK0nKysqqsnGKxriScSqibdu2VbZtAAAAAABQudwyuPHz87M/zs3Nvez6OTk5klTsVt6VOU7RGFcyzuVOrTp27Ji6desm6cJ1dxo2bFih7QMAAAAAgMs7cuRIpR8w4ZbBTY0aNeyPy3NaUkZGhqTynVZ1peMUjXEl41zu+jmX9hQcHFyh7QMAAAAAgMurikuTuOVdpfz8/FS7dm1Jl7+w75kzZ+yhSkWuJSOZA5XLjXPxUTMVHQcAAAAAALgmtwxupP9d62Xfvn3Kz88vdb1du3bZH7dp0+aKxrh0O5U9DgAAAAAAcE1uG9xcd911ki6corRx48ZS11u1apX9cc+ePSs0RvPmzdWgQYNi2ynJzz//LElq2LChmjVrVqFxAAAAAACAa3Lb4ObOO++0P547d26J6xQWFmr+/PmSpNDQUPXt27dCY9hsNg0YMEDShSNq1q1bV+J669atsx9xM2DAANlstgqNAwAAAAAAXJPbBjfdunVTr169JEmzZ89WXFxcsXWmTZumnTt3SpIeeeQReXt7m5avXLlSNptNNptNo0aNKnGcRx99VJ6enpKkhx56qNitvrOysvTQQw9Jkry8vPToo49ezcsCAAAAAAAuxG2DG0l666235O/vr/z8fN1888169dVXtW7dOq1YsULjx4/XU089JUmKjIzUxIkTr2iMyMhIPfnkk5KkhIQE9ezZU4sXL1ZCQoIWL16snj17KiEhQZL05JNPqlWrVpXz4gAAAAAAgNNzy9uBF+ncubMWL16sYcOGKT09Xc8++2yxdSIjI7V8+XLTrb0ravLkyTp58qTmzJmjxMREDR48uNg6Y8aM0d/+9rcrHgMAAAAAALgetz7iRpL69++vrVu36rHHHlNkZKQCAgIUGhqq6Oho/eMf/1BiYqIiIiKuagwPDw/Nnj1by5cv14ABA9SgQQP5+PioQYMGGjBggL7++mvNmjVLHh5u/38HAAAAAAC4iM0wDMPqJlC1kpOT1bhxY0lSUlKSGjVqZHFHAAAAAAC4nqr4/M0hHgAAAAAAAA6K4AYAAAAAAMBBEdwAAAAAAAA4KIIbAAAAAAAAB0VwAwAAAAAA4KAIbgAAAAAAABwUwQ0AAAAAAICDIrgBAAAAAABwUAQ3AAAAAAAADorgBgAAAAAAwEER3AAAAAAAADgoghsAAAAAAAAHRXADAAAAAADgoAhuAAAAAAAAHBTBDQAAAAAAgIMiuAEAAAAAAHBQBDcAAAAAAAAOiuAGAAAAAADAQRHcAAAAAAAAOCgvqxtA1cvPz7c/PnbsmIWdAAAAAADgui7+zH3xZ/GrQXDjBlJSUuyPu3XrZmEnAAAAAAC4h5SUFDVr1uyqt8OpUgAAAAAAAA7KZhiGYXUTqFrZ2dnatm2bJKlOnTry8nKNA62OHTtmP4IoPj5e9evXt7gjoDjmKZwB8xTOgHkKZ8FchTNgnlad/Px8+1kvHTp0kJ+f31Vv0zU+waNMfn5+6tq1q9VtVKn69eurUaNGVrcBlIl5CmfAPIUzYJ7CWTBX4QyYp5WvMk6PuhinSgEAAAAAADgoghsAAAAAAAAHRXADAAAAAADgoAhuAAAAAAAAHBTBDQAAAAAAgIMiuAEAAAAAAHBQBDcAAAAAAAAOymYYhmF1EwAAAAAAACiOI24AAAAAAAAcFMENAAAAAACAgyK4AQAAAAAAcFAENwAAAAAAAA6K4AYAAAAAAMBBEdwAAAAAAAA4KIIbAAAAAAAAB0VwAwAAAAAA4KAIbgAAAAAAABwUwQ0AAAAAAICDIrhBlTp06JAmTpyo1q1bKzAwULVq1VLXrl01depUZWZmXtW2d+7cqXfffVcjR45Uly5d1KhRI/n5+SkwMFAtWrTQoEGDtHTpUhmGUeZ2Ro0aJZvNVq6fgwcPXlXPcExVOU9Lk5mZqRYtWtjnVrNmzcr9vClTpqhr166qVauWAgMD1bp1a02cOFGHDh2qkl7hGJxhnvbp06fc+1O4pqqcp/PmzSv3/Jo3b95lt8f+1L05w1xln4rqfO//4YcfNGrUKEVERCgwMFAhISGKjIzUPffcow8++EDnz58v8/nsU6uYAVSRL7/80ggODjYklfgTGRlp7N2794q3P3To0FK3ffFP7969jdTU1FK3M3LkyHJtR5Jx4MCBK+4Xjqmq52lpJk6caBqnadOml33O3r17jVatWpXaa3BwsLFs2bJK7xXWc5Z52rt373LvT+F6qnqezp07t9zza+7cuWVui/2pe3OWuco+1b1V13v/6dOnjQEDBlx2jiUmJpa6DfapVc9LQBVITEzUoEGDlJWVpaCgID3zzDPq27evsrKytGjRIs2cOVN79uxRv379lJCQoBo1alR4DC8vL3Xv3l09e/ZUhw4dVK9ePdWpU0dnzpzRrl27NH36dG3fvl2rVq1S//79tWbNGnl4lH6QWYMGDfTtt9+WOWbDhg0r3CccV3XM09LGffPNN+Xn5ydvb2+dO3fuss85d+6c+vXrp71790qSxo0bp8GDB8vf318rVqzQq6++qvT0dA0aNEi//PKLOnXqVCm9wnrONE+LREdHa+7cuZXSB5xDdc/Tb7/9Vg0aNCh1eaNGjUpdxv7UvTnTXC3CPtX9VNc8TUtL00033aSNGzdKku666y7dc889atmypTw9PZWUlKRVq1ZpyZIlpW6DfWo1sTo5gmvq1auXIcnw8vIy1q5dW2z5lClT7AnspEmTrmiMvLy8Mpfn5+cbd999t32cpUuXlrhe0RE35TniAa6lOubppfLz842oqChDkvHXv/7VaNq0abnm3wsvvGDvZcqUKcWW//LLL4aXl5f9KDO4Dmeap0XfDjMH3U91zNOLj2K4miNg2Z+6N2eaq+xT3Vd1vfcPHz7ckGT4+vqW+lnJMAyjsLCw1M9e7FOrB8ENKt369evtv7zjx48vcZ2CggKjTZs2hiQjNDTUyM3NrZJe4uLi7L088cQTJa5DcOOerJqn06ZNMyQZ11xzjZGTk1OuD8S5ublGSEiIIclo06aNUVBQUOJ648ePt7+m+Pj4q+4V1nOmeWoYfMhwV9U1TyvjwzD7U/fmTHPVMNinuqvqmqerV6+2jzN16tQr6pV9avXh4sSodF988YX98ejRo0tcx8PDQyNGjJAknT17VitWrKiSXi4+bDA7O7tKxoBzsmKeHjp0SH/5y18kSf/85z/l4+NTruetWLFCaWlpkqSRI0eWesrfqFGj7I8///zzq+oVjsGZ5inclyO9718O+1P35kxzFe6ruubpu+++K0kKCQnRhAkTKt6o2KdWJ4IbVLo1a9ZIkgIDAxUVFVXqer1797Y//uWXX6qkl0WLFtkft27dukrGgHOyYp4++OCDysjI0PDhw9WnT59yP6+o10v7uVR0dLQCAgIkVd3vFKqXM81TuC9Het+/HPan7s2Z5ircV3XM09zcXC1dulSSdNNNN8nPz0+SVFBQoKSkJB08eLBcX3qzT60+BDeodDt37pQkRUREyMur9OtfXxykFD2nMqSmpiouLk5jxozR5MmTJUlhYWEaOnRomc87deqUevfurdq1a8vX11f169fXLbfconfffbfKbrUL61T3PF20aJG+/vpr1axZU9OmTavQc3fs2FFiP5fy8vJSRESEpMr9nYJ1nGmeXmzXrl3q3r27QkND5efnp0aNGmnAgAGaP3++8vLyrni7cExWvO+PHj1aDRo0kI+Pj8LCwhQTE6Pnn39eR44cKfN57E/dmzPN1YuxT3Uv1TFPt2zZYg9mOnTooPT0dD366KMKCwtTkyZN1Lx5c4WEhOimm27SypUrS90O+9TqQ3CDSpWdna3U1FRJl79Kfs2aNRUYGChJSkpKuqpx+/TpI5vNJpvNpjp16uh3v/ud5syZI8MwFBYWps8//1yhoaFlbuP8+fP6+eefdfr0aeXm5ur48eP67rvv9NBDDykyMlJr1669qh7hOKp7np45c0aPPvqoJOnvf/+76tSpU6HnJycnS7rwzcvl5nHjxo0lSSkpKcrJyalwr3AczjZPL3bixAnFx8crLS1NOTk5OnLkiL788kuNHDlSnTp14o82F2LV+/7KlSt17Ngx5eXl6dSpU1q/fr0mT56siIgITZ8+vdTnsT91X842Vy/GPtV9VNc8vThwKSwsVHR0tN566y2dPXvWXs/NzdUPP/yg66+/Xv/4xz9K3A771OrD7cBRqS6+XWxQUNBl1w8MDFRGRobOnz9fJf08/PDDeuGFFxQWFlbqOjabTTExMerfv7+6dOmiunXrKjs7W9u2bdPs2bMVHx+vI0eO6Oabb9bq1avVuXPnKukV1ae65+mTTz6pEydOqEePHho3blyFn1/Ub3l7LXL+/Hn5+vpWeDw4Bmebp9KFc+5vuOEG3XbbberYsaNq166tc+fOadOmTZo+fbp27typHTt2qG/fvoqPj1eTJk2uaBw4juqepy1atNDdd9+tHj162D8E7N+/X0uWLNFnn32m7Oxs/fGPf5TNZlNsbGyp/bI/dT/ONlcl9qnuqLrm6enTp+2P//GPfyg7O1u33nqr/vrXv+raa69Venq6lixZoqefflppaWl6+umn1bp1aw0YMKDEftmnVgOrr44M13L48GH7FcOHDx9+2fUbN25sSDJatmx5VePu37/f2LZtm7F161bj559/Nl5//XWjVatWhoeHh3H77bcbx48fL/W5Z86cKXVZYWGh8eyzz9pfU5cuXYzCwsKr6hXWq855umrVKsNmsxleXl7Gli1bii0vz916WrRoYUgyGjdufNnxim7rKMlISkqqcL9wHM42Tw2j7P1pbm6u/S5+koy77rqrwn3C8VTnPD179myZ78HLli0zvL29DUlGQECAcezYsWLrsD91X842Vw2Dfao7qq55+vLLL9vHkWTcdNNNRn5+frH1Vq9ebXh4eNjvGnXpvGafWn04VQqVqujCVtKFw+sup+gwOX9//6sat3nz5mrfvr06dOigXr166bHHHtPWrVt122236auvvlLXrl3th/JdqqzD+mw2myZPnqwbbrhBkrRp0yZOmXIB1TVPc3JyFBsbK8Mw9Mgjj+jaa6+tWKP/VdRvRXqVrv73CtZytnkqlb0/9fb21qxZs3TNNddIunBXiYpc4wGOqTrf90NCQmSz2Updfvvtt9vviJaZmanZs2cXW4f9qftytrkqsU91R9U1Ty8eR7pw1I2np2ex9a677jrdfffdki5cm2bbtm0lbod9atUjuEGluvj22+U5ZC8jI0NS+Q6vqyg/Pz/NnTtXAQEBSkpK0lNPPXXF2xo/frz98apVqyqjPViouubp5MmTtXv3bjVu3FgvvfRSxZq8SFG/FelVqprfK1QfZ5un5eHl5aUxY8bY/83+1Pk50vu+JMXGxto/MJc0v9ifui9nm6vlwT7V9VTXPL14nDp16pR5KYhbbrnF/njDhg0lbod9atXjGjeoVH5+fqpdu7ZOnTpV6hEuRc6cOWP/BS4697eyhYWFqWfPnvr++++1dOlS5eXlydvbu8Lbadu2rf0x32Y4v+qap0UXcrvxxhu1bNmyEtcp2nZGRob99vXh4eG6/vrr7es0atRI69evV0ZGhs6ePVvmN3BFF6erU6cO5w47OWebp+XF/tS1ONr7fnh4uGrXrq3U1NQS5xf7U/flbHO1vNinupbqmqcXr3+5iyBfvG5KSoppGfvU6kNwg0rXtm1brV69Wvv27VN+fn6pt7HbtWuX/XGbNm2qrJ+iO6NkZmYqNTVV9evXr/A2yjrcFc6pOuZp0WGjc+fO1dy5c8tcNzU1VUOGDJEk9e7d2/SBuG3btlqyZIm9n5iYmBK3kZ+fr99+++2KeoVjcqZ5Wl7sT12Po73vlzXH2J+6N2eaq9W5DTiW6pin7dq1sz8uKCgoc92Ll1/aC/vU6sOpUqh01113naQL38xu3Lix1PUuPpyzZ8+eVdbPxd8+XOlheRffMq9BgwZX3ROs52jztCxFvUplHwadkJBg/+bFql5RuZxpnpYX+1PX40jzNCUlxX4r3ZLmF/tT9+ZMc7W82Ke6nuqYp02bNrXfhezgwYMyDKPUdYsCF0lq2LBhib1e2s+l2KdWAosvjgwXtH79evsVw8ePH1/iOgUFBUabNm0MSUZoaKiRm5tbJb0kJSUZPj4+5bobSlluvPFG+2tavXp15TUIyzjKPC3P3XpycnKMkJCQUq/oX2T8+PH21xQfH1/pvaL6OdM8LY+8vDx7r5KMw4cPV06DsJSjzFPDMIy//e1v9l5efvnlYsvZn7o3Z5qr5cE+1TVV1zx97LHH7ON8//33pa7Xp0+fUucY+9TqQ3CDKtGrVy9DkuHl5WWsXbu22PIpU6bYf3knTZpUbPmKFSvsy0eOHFls+e7du40ff/yxzB7Onj1r70OS8cILLxRbJy4uzjh69Gip2ygsLDSee+45+zY6duzI7cBdSFXP0/Io7wfiF154wT7WlClTii1fu3at4eXlZUgyevfufUW9wDE5yzz96aefKnTr2v79+19RL3BMVT1PDxw4YGzatKnMHpYtW2b/ssbf399ITk4ucT32p+7NWeYq+1T3Vh3v/YcOHTL8/PwMSUaHDh2MtLS0YussWLDAvp1+/fqVuB32qdWD4AZVYtOmTYa/v78hyQgKCjJeeeUVIy4uzvjpp5+M2NhY+y93ZGSkkZ6eXuz5l9vZFC3v2LGjMWnSJOPLL7804uPjjU2bNhlff/218dxzzxn16tWzb6N9+/ZGRkZGse1MmjTJ8PX1NQYMGGC8++67xk8//WRs2rTJiIuLM6ZPn250797dvo2AgAASYhdT1fO0PMob3KSnpxuRkZH28WJjY42ffvrJiIuLM1555RUjKCjI/gdgYmLiFfUCx+Qs83TkyJFGUFCQcd999xkzZswwVq1aZSQmJhqrV6823nzzTaNt27b2PsLDw439+/dfUS9wTNX1vt+jRw/jlVdeMZYvX25s2LDB2LBhg7F48WJj4MCBhs1ms2/jvffeK7VX9qfuzVnmKvtU91Zd7/0XB0DXXHONMWfOHCMhIcH46aefjAkTJhienp6GJCM4ONjYs2dPidtgn1o9CG5QZb788ksjODjY/kt86U9kZKSxd+/eEp9b3jfF8vz069fPOHnyZInjTJo0qVzbaNKkibFmzZrK/M8DB1GV87Q8KnIKyt69e41WrVqV2mtwcLCxbNmyK+oDjs0Z5unF3/yW9dOhQwfj119/vaI+4Ngc4X0/ICDAmD59+mV7ZX/q3pxhrrJPRXW99z/99NOmMPHSn/Dw8BKP+rkY+9Sqx12lUGX69++vrVu36q233tLy5cuVnJwsHx8fRUREaODAgZowYYICAgKuaNs9e/bUt99+qx9++EEJCQlKTk7WiRMnlJmZqeDgYDVv3lwxMTEaMmRImRfAGj16tOrWrau4uDht3bpVJ0+e1KlTp+Tl5aWwsDB16dJF/fv313333Sc/P78r/U8BB1aV87SyRUREKDExUe+9954+/fRT7du3T7m5uWrcuLFuu+02PfLII2ratKnVbaIKOMM8/fOf/6xOnTopLi5OO3bsUEpKik6fPi1fX1/VrVtX0dHRuueee3TXXXfJ09PT0l5RNapynkZFRemjjz5SXFycEhISdOzYMaWmpio/P181a9ZUu3btdMMNN2js2LEKDw+/7PbYn7o3Z5ir7FNRXe/9r776qu644w598MEHWr16tY4dOyY/Pz9FRkbqjjvu0EMPPaSQkJAyt8E+terZDKOMS0gDAAAAAADAMtwOHAAAAAAAwEER3AAAAAAAADgoghsAAAAAAAAHRXADAAAAAADgoAhuAAAAAAAAHBTBDQAAAAAAgIMiuAEAAAAAAHBQBDcAAAAAAAAOiuAGAAAAAADAQRHcAAAAAAAAOCiCGwAAAAAAAAdFcAMAAAAAAOCgCG4AAAAAAAAcFMENAAAAAACAgyK4AQAAAAAAcFAENwAAAAAAAA6K4AYAAMBBNGvWTDabTaNGjbK6lRKtXLlSNptNNptNK1eutLodAADcAsENAABwehcHCpf+BAQEqGnTprrzzjv1ySefKD8/3+p2q8zBgwdNr93Dw0OHDh0q13MjIyNNz503b17VNgsAAMqF4AYAALi0rKwsHT58WEuXLtXQoUP1u9/9TsePH7e6rWphGIY+/vjjy663bt067d27txo6AgAAFUVwAwAAXMoDDzygbdu22X/i4uL0zjvvqFmzZpKkDRs2aMCAATIMw9pGq5ifn58kacGCBZddt2idoueUpk+fPjIMQ4ZhqE+fPlfdIwAAuDyCGwAA4FLCw8PVvn17+09MTIwmTJigTZs2KSIiQpIUHx+vr776yuJOq9Ydd9whSdq1a5cSEhJKXS8vL0+LFy+WJA0YMKBaegMAAOVHcAMAANxCzZo19cwzz9j//Z///MfCbqpemzZtFB0dLanso26+/vprnTp1Sj4+Pho0aFB1tQcAAMqJ4AYAALiNbt262R+XdNHelJQUPf/88+rcubNCQ0Pl5+enZs2aafjw4VqzZk25xjh48KAee+wxtWvXTjVq1FBAQIBatWql8ePHa9u2bZX2Wspj+PDhkqRFixaVelHm+fPnS5Juv/121axZs8ztlXVXqVdeecW+bMqUKaVuY+PGjfLx8ZHNZlPfvn1VWFhYgVcEAID7IbgBAABuw9vb2/64oKDAtOy7775TRESEJk+erM2bNystLU05OTk6dOiQPvroI/Xq1UsTJkwoM2iYP3++WrdurTfffFM7duzQ+fPnlZWVpX379mnGjBnq3LmzXn311Sp7fZcaPHiwvLy8dPLkSX377bfFlp85c0bLly+X9L+Q50o9/fTT6tWrlyTphRde0ObNm4utk5mZqaFDhyovL0+hoaGaP3++PDz4cxQAgLLwTgkAANzGxUe8NGjQwP548+bN6t+/v9LT0+Xt7a3HHntMK1asUHx8vKZPn67mzZtLkt577z3T6VYXW758uUaNGqWcnBwFBQVp0qRJWr16teLi4jRt2jSFhYWpoKBAzz77rD744IOqfaH/FR4erltuuUVSyadL/etf/1JOTo5q166t22677arG8vDw0IIFCxQSEqLc3Fzdd999ysrKMq3z+OOPa/fu3ZKkDz74QI0bN76qMQEAcAcENwAAwC3k5+dr2rRp9n9ffFek2NhY5ebmytPTU1999ZVef/119enTR127dlVsbKw2btyotm3bSpJee+01/frrr6Zt5+XlKTY2VoZhKCgoSKtXr9aLL76o6667TjExMXr88ceVkJCg+vXrS5KeeOIJpaamVv2LljRixAhJ0pdffqn09HTTsqIwZ9CgQfLx8bnqsZo2bar33ntPkrRz5049+eST9mXLli3T9OnTJUlDhw7V4MGDr3o8AADcAcEN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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 448, + "width": 567 + } + }, + "output_type": "display_data" + } + ], + "source": [ + "df = withdrawall_base\n", + "df\n", + "\n", + "plt.axhline(0, c=\"black\", linewidth=0.4)\n", + "plt.plot(df['before_mix'], df['after_profit'])\n", + "# plt.ylim([-1e18,1e18])\n", + "plt.xlabel(\"Pool Mix\")\n", + "plt.ylabel(\"Withdraw All Profit\")\n", + "\n", + "display(df['after_profit'].min() / 1e18 ) \n", + "df\n", + "\n", + "\n", + "# for before_mix, rows in df.groupby(df['before_mix']):\n", + "# " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f882432-f9a5-467f-8489-9ebea6d32e25", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fcd1dc9-0bfd-467b-8760-e30511cbbd38", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "048342ce-bfe9-40f4-8fe9-cd9cfde68ef2", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/brownie/balancer_test/balance_stats.csv b/brownie/balancer_test/balance_stats.csv new file mode 100644 index 0000000000..16ba380adf --- /dev/null +++ b/brownie/balancer_test/balance_stats.csv @@ -0,0 +1,31 @@ +,action,action_mix,pre_vault,pre_pool_0,pre_pool_1,before_vault,before_pool_0,before_pool_1,after_vault,after_pool_0,after_pool_1 +0,balance,-1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195 +1,balance,-0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195 +2,balance,-0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195 +3,balance,0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195 +4,balance,0.6000000000000001,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195 +5,balance,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195 +6,balance,-1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712572189372348624593,18242934255027827229177,11548952971324396342649 +7,balance,-0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712572189372348624593,18242934255027827229177,11548952971324396342649 +8,balance,-0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712572189372348624593,18242934255027827229177,11548952971324396342649 +9,balance,0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712572189372348624593,18242934255027827229177,11548952971324396342649 +10,balance,0.6000000000000001,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712572189372348624593,18242934255027827229177,11548952971324396342649 +11,balance,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712572189372348624593,18242934255027827229177,11548952971324396342649 +12,balance,-1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66712907445086235643663,26242934255027827229177,3353956202615535828290 +13,balance,-0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66712907445086235643663,26242934255027827229177,3353956202615535828290 +14,balance,-0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66712907445086235643663,26242934255027827229177,3353956202615535828290 +15,balance,0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66712907445086235643663,26242934255027827229177,3353956202615535828290 +16,balance,0.6000000000000001,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66712907445086235643663,26242934255027827229177,3353956202615535828290 +17,balance,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66712907445086235643663,26242934255027827229177,3353956202615535828290 +18,balance,-1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712558895552736211885,10573784870046460961396,19857742858560606821195 +19,balance,-0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712558895552736211885,10573784870046460961396,19857742858560606821195 +20,balance,-0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712558895552736211885,10573784870046460961396,19857742858560606821195 +21,balance,0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712558895552736211885,10573784870046460961396,19857742858560606821195 +22,balance,0.6000000000000001,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712558895552736211885,10573784870046460961396,19857742858560606821195 +23,balance,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712558895552736211885,10573784870046460961396,19857742858560606821195 +24,balance,-1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66712869686872145535099,3542292303059742178292,27857742858560606821195 +25,balance,-0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66712869686872145535099,3542292303059742178292,27857742858560606821195 +26,balance,-0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66712869686872145535099,3542292303059742178292,27857742858560606821195 +27,balance,0.19999999999999996,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66712869686872145535099,3542292303059742178292,27857742858560606821195 +28,balance,0.6000000000000001,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66712869686872145535099,3542292303059742178292,27857742858560606821195 +29,balance,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66712869686872145535099,3542292303059742178292,27857742858560606821195 diff --git a/brownie/balancer_test/deposit_stats.csv b/brownie/balancer_test/deposit_stats.csv new file mode 100644 index 0000000000..7eece267aa --- /dev/null +++ b/brownie/balancer_test/deposit_stats.csv @@ -0,0 +1,306 @@ +,action,action_mix,start_vault,start_value_in_vault,start_strat_check_balance,pre_vault,pre_pool_0,pre_pool_1,before_vault,before_value_in_vault,before_strat_check_balance,before_pool_0,before_pool_1,after_vault,after_strat_check_balance,after_value_in_vault,after_pool_0,after_pool_1,end_vault,end_strat_check_balance,end_value_in_vault +0,deposit,0.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66710862971615921158623,4998478840701533411134,61712384130914387747490,16229435309620094429177,15580869060997576531443,66711041864010359355202,0,66711041864010359355202 +1,deposit,0.016666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66710952327674698820238,4998568196760311234280,61712384130914387585959,16198664367055643729177,15614202394330909863411,66711119456681643338572,0,66711119456681643338572 +2,deposit,0.03333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711039004113313205288,4998654873198925889188,61712384130914387316101,16167893424491193129177,15647535727664243195379,66711194773337564382088,0,66711194773337564382088 +3,deposit,0.05,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711123004518362150713,4998738873603974675258,61712384130914387475456,16137122481926742129177,15680869060997576531443,66711267817058432868707,0,66711267817058432868707 +4,deposit,0.06666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711204332346976121908,4998820201432588803889,61712384130914387318021,16106351539362291429177,15714202394330909859315,66711338590813454889066,0,66711338590813454889066 +5,deposit,0.08333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711282990927230723865,4998898860012843238298,61712384130914387485568,16075580596797840429177,15747535727664243187187,66711407097461089938071,0,66711407097461089938071 +6,deposit,0.1,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711358983458543479382,4998974852544155950980,61712384130914387528403,16044809654233389529177,15780869060997576531443,66711473339749395283659,0,66711473339749395283659 +7,deposit,0.11666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711432313012054772615,4999048182097667309705,61712384130914387462912,16014038711668938729177,15814202394330909875699,66711537320316356221232,0,66711537320316356221232 +8,deposit,0.13333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711502982530993260926,4999118851616605614085,61712384130914387646843,15983267769104487729177,15847535727664243187187,66711599041690203193330,0,66711599041690203193330 +9,deposit,0.15,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711570994831025973618,4999186863916638392268,61712384130914387581351,15952496826540036929177,15880869060997576531443,66711658506289715429523,0,66711658506289715429523 +10,deposit,0.16666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711636352600592759437,4999252221686205319139,61712384130914387440300,15921725883975586229177,15914202394330909842931,66711715716424511117435,0,66711715716424511117435 +11,deposit,0.18333333333333332,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711699058401225484332,4999314927486838185084,61712384130914387299249,15890954941411135529177,15947535727664243154419,66711770674295324179400,0,66711770674295324179400 +12,deposit,0.2,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711759114667851946967,4999374983753464529325,61712384130914387417644,15860183998846684529177,15980869060997576531443,66711823381994268214584,0,66711823381994268214584 +13,deposit,0.21666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711816523709084631010,4999432392794697094972,61712384130914387536039,15829413056282233529177,16014202394330909908467,66711873841505086804185,0,66711873841505086804185 +14,deposit,0.23333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711871287707494217394,4999487156793106714081,61712384130914387503315,15798642113717782729177,16047535727664243219955,66711922054703390885503,0,66711922054703390885503 +15,deposit,0.25,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711923408719868096543,4999539277805480625953,61712384130914387470592,15767871171153331929177,16080869060997576531443,66711968023356883123426,0,66711968023356883123426 +16,deposit,0.26666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711972888677453813334,4999588757763066483794,61712384130914387329541,15737100228588881229177,16114202394330909842931,66712011749125569071887,0,66712011749125569071887 +17,deposit,0.2833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712019729386187576699,4999635598471800063228,61712384130914387513472,15706329286024430229177,16147535727664243154419,66712053233561955564699,0,66712053233561955564699 +18,deposit,0.3,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712063932526907799380,4999679801612520275843,61712384130914387523539,15675558343459979329177,16180869060997576531443,66712092478111236098470,0,66712092478111236098470 +19,deposit,0.31666666666666665,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712105499655553814258,4999721368741166474562,61712384130914387339697,15644787400895528729177,16214202394330909777395,66712129484111463178758,0,66712129484111463178758 +20,deposit,0.3333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712144432203349673613,4999760301288962432176,61712384130914387241438,15614016458331077929177,16247535727664243154419,66712164252793708073946,0,66712164252793708073946 +21,deposit,0.35,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712180731476973311708,4999796600562585951876,61712384130914387359833,15583245515766626929177,16280869060997576531443,66712196785282207573632,0,66712196785282207573632 +22,deposit,0.36666666666666664,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712214398658710799654,4999830267744323407010,61712384130914387392645,15552474573202176129177,16314202394330909777395,66712227082594497985573,0,66712227082594497985573 +23,deposit,0.38333333333333336,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712245434806596013532,4999861303892208525239,61712384130914387488295,15521703630637725029177,16347535727664243285491,66712255145641536562099,0,66712255145641536562099 +24,deposit,0.4,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712273840854535457469,4999889709940148044691,61712384130914387412780,15490932688073274329177,16380869060997576531443,66712280975227809828554,0,66712280975227809828554 +25,deposit,0.4166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712299617612418534584,4999915486698030895082,61712384130914387639503,15460161745508823229177,16414202394330909908467,66712304572051429550482,0,66712304572051429550482 +26,deposit,0.43333333333333335,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712322765766213264422,4999938634851825723180,61712384130914387541243,15429390802944372429177,16447535727664243285491,66712325936704215926534,0,66712325936704215926534 +27,deposit,0.45,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712343285878047184686,4999959154963659827286,61712384130914387357401,15398619860379921829177,16480869060997576531443,66712345069671768069805,0,66712345069671768069805 +28,deposit,0.4666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712361178386273809525,4999977047471886442059,61712384130914387367468,15367848917815470929177,16514202394330909908467,66712361971333521902781,0,66712361971333521902781 +29,deposit,0.48333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712376443605524389219,4999992312691136880613,61712384130914387508608,15337077975251020029177,16547535727664243154419,66712376641962795231057,0,66712376641962795231057 +30,deposit,0.5,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712389080830559912205,5000004949916172393531,61712384130914387518676,15306307032686569129177,16580869060997576531443,66712389080830635217932,0,66712389080830635217932 +31,deposit,0.5166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712376445949549507902,4999992315035162195814,61712384130914387312089,15275536090122118429177,16614202394330909908467,66712376643818197772650,0,66712376643818197772650 +32,deposit,0.5333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712361183970666231765,4999977053056278778539,61712384130914387453228,15244765147557667529177,16647535727664243154419,66712361975940649595613,0,66712361975940649595613 +33,deposit,0.55,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712343294703116231540,4999959163788728790990,61712384130914387440551,15213994204993216529177,16680869060997576662515,66712345077030889017059,0,66712345077030889017059 +34,deposit,0.5666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712322777832420853187,4999938646918033248753,61712384130914387604436,15183223262428765729177,16714202394330909777395,66712325946815729016518,0,66712325946815729016518 +35,deposit,0.5833333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712299632920379201850,4999915502005991718420,61712384130914387483431,15152452319864314829177,16747535727664243285491,66712304584915864671820,0,66712304584915864671820 +36,deposit,0.6,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712273859405016451821,4999889728490629043907,61712384130914387407916,15121681377299864129177,16780869060997576531443,66712280990845827845340,0,66712280990845827845340 +37,deposit,0.6166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712245456600517393786,4999861325686129998549,61712384130914387395239,15090910434735413129177,16814202394330910039539,66712255164013929406449,0,66712255164013929406449 +38,deposit,0.6333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712214423697145491667,4999830292782758126454,61712384130914387365214,15060139492170962629177,16847535727664243023347,66712227103722188680430,0,66712227103722188680430 +39,deposit,0.65,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712180759761147223296,4999796628846759762435,61712384130914387460864,15029368549606511529177,16880869060997576531443,66712196809166250352157,0,66712196809166250352157 +40,deposit,0.6666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712144463734642001550,4999760332820254616203,61712384130914387385349,14998597607042060829177,16914202394330909777395,66712164279435288761849,0,66712164279435288761849 +41,deposit,0.6833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712105534435496996448,4999721403521109515450,61712384130914387480999,14967826664477609729177,16947535727664243285491,66712129513511898956439,0,66712129513511898956439 +42,deposit,0.7,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712063970557187838244,4999679839642800432761,61712384130914387405485,14937055721913159029177,16980869060997576531443,66712092510271975851321,0,66712092510271975851321 +43,deposit,0.7166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66712019770668644158218,4999635639754256719922,61712384130914387438297,14906284779348708229177,17014202394330909777395,66712053268484580139271,0,66712053268484580139271 +44,deposit,0.7333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711972933214080576214,4999588802299693105107,61712384130914387471109,14875513836784257429177,17047535727664243023347,66712011786811791222758,0,66712011786811791222758 +45,deposit,0.75,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711923456512812851407,4999539325598425392977,61712384130914387458432,14844742894219806429177,17080869060997576531443,66711968063808547988996,0,66711968063808547988996 +46,deposit,0.7666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711871338759059162899,4999487207844671717147,61712384130914387445755,14813971951655355429177,17114202394330910039539,66711922097922475994659,0,66711922097922475994659 +47,deposit,0.7833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711816578021726720279,4999432447107339306711,61712384130914387413571,14783201009090904689177,17147535727664243285491,66711873887493702423344,0,66711873887493702423344 +48,deposit,0.8,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711759172244183061904,4999375041329795658853,61712384130914387403053,14752430066526453929177,17180869060997576531443,66711823430754657553229,0,66711823430754657553229 +49,deposit,0.8166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711699119244012813799,4999314988329625421266,61712384130914387392534,14721659123962003169177,17214202394330909777395,66711770725829863676952,0,66711770725829863676952 +50,deposit,0.8333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711636416712759127959,4999252285798371704772,61712384130914387423188,14690888181397552129177,17247535727664243285491,66711715770735710736246,0,66711715770735710736246 +51,deposit,0.85,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711571062215650190140,4999186931301262788305,61712384130914387401837,14660117238833101379177,17280869060997576531443,66711658563380219014602,0,66711658563380219014602 +52,deposit,0.8666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711503053191310440480,4999118922276923062154,61712384130914387378327,14629346296268650389177,17314202394330910039539,66711599101562788636609,0,66711599101562788636609 +53,deposit,0.8833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711432386951456737781,4999048256037069324485,61712384130914387413298,14598575353704199829177,17347535727664243023347,66711537382973935852677,0,66711537382973935852677 +54,deposit,0.9,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711359060680579256166,4998974929766191855546,61712384130914387400621,14567804411139748829177,17380869060997576531443,66711473405195016352171,0,66711473405195016352171 +55,deposit,0.9166666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711283071435606768627,4998898940521219378526,61712384130914387390102,14537033468575298069177,17414202394330909777395,66711407165697934808140,0,66711407165697934808140 +56,deposit,0.9333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711204416145556902982,4998820285231169514727,61712384130914387388258,14506262526010847059177,17447535727664243285491,66711338661844841443658,0,66711338661844841443658 +57,deposit,0.95,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711123091611170660004,4998738960696783260600,61712384130914387399405,14475491583446396279177,17480869060997576531443,66711267890887815073272,0,66711267890887815073272 +58,deposit,0.9666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66711039094504531280931,4998654963590143870381,61712384130914387410552,14444720640881945499177,17514202394330909777395,66711194849968532500396,0,66711194849968532500396 +59,deposit,0.9833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66710952421368667722054,4998568290454280315522,61712384130914387406533,14413949698317494733177,17547535727664243023347,66711119536117924410377,0,66711119536117924410377 +60,deposit,1.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712394411522828879752,63712384130914387398189,3000010280608441481564,14383178755753043729177,15580924427536831499051,66710863068617142130018,4998478937702754731830,61712384130914387398189,14383178755753043729177,17580869060997576531443,66711041946255817777800,0,66711041946255817777800 +61,deposit,0.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66705876494723452789389,4993492363809065041901,61712384130914387747490,18228984064630769912624,13421241891906475353115,66707723020594018389796,0,66707723020594018389796 +62,deposit,0.016666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66706154043337188328020,4993769912422800742063,61712384130914387585959,18198213122066319212624,13454575225239808685083,66707960552724087546731,0,66707960552724087546731 +63,deposit,0.03333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66706428369866312719480,4994044238951925403381,61712384130914387316101,18167442179501868612624,13487908558573142017051,66708195343402506825387,0,66708195343402506825387 +64,deposit,0.05,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66706699488039964177867,4994315357125576702413,61712384130914387475456,18136671236937417612624,13521241891906475353115,66708427404428258297637,0,66708427404428258297637 +65,deposit,0.06666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66706967411389856660160,4994583280475469342141,61712384130914387318021,18105900294372966912624,13554575225239808680987,66708656747430246284772,0,66708656747430246284772 +66,deposit,0.08333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66707232153252115789171,4994848022337728303605,61712384130914387485568,18075129351808515912624,13587908558573142008859,66708883383868892927733,0,66708883383868892927733 +67,deposit,0.1,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66707493726769082850226,4995109595854695321825,61712384130914387528403,18044358409244065012624,13621241891906475353115,66709107325037706164840,0,66709107325037706164840 +68,deposit,0.11666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66707752144891087319593,4995368013976699856683,61712384130914387462912,18013587466679614212624,13654575225239808697371,66709328582064820358148,0,66709328582064820358148 +69,deposit,0.13333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66708007420378188413864,4995623289463800767022,61712384130914387646843,17982816524115163212624,13687908558573142008859,66709547165914509619742,0,66709547165914509619742 +70,deposit,0.15,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66708259565801885966510,4995875434887498385160,61712384130914387581351,17952045581550712412624,13721241891906475353115,66709763087388674620613,0,66709763087388674620613 +71,deposit,0.16666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66708508593546801165055,4996124462632413724756,61712384130914387440300,17921274638986261712624,13754575225239808664603,66709976357128303058611,0,66709976357128303058611 +72,deposit,0.18333333333333332,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66708754515812327772414,4996370384897940473167,61712384130914387299249,17890503696421811012624,13787908558573141976091,66710186985614904324673,0,66710186985614904324673 +73,deposit,0.2,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66708997344614253831243,4996613213699866413601,61712384130914387417644,17859732753857360012624,13821241891906475353115,66710394983171918396347,0,66710394983171918396347 +74,deposit,0.21666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66709237091786354720988,4996852960871967184950,61712384130914387536039,17828961811292909012624,13854575225239808730139,66710600359966100113165,0,66710600359966100113165 +75,deposit,0.23333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66709473768981957666290,4997089638067570162977,61712384130914387503315,17798190868728458212624,13887908558573142041627,66710803126008878013848,0,66710803126008878013848 +76,deposit,0.25,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66709707387675478167473,4997323256761090696882,61712384130914387470592,17767419926164007412624,13921241891906475353115,66711003291157689156591,0,66711003291157689156591 +77,deposit,0.26666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66709937959163928841084,4997553828249541511544,61712384130914387329541,17736648983599556712624,13954575225239808664603,66711200865117289714984,0,66711200865117289714984 +78,deposit,0.2833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66710165494568401007865,4997781363654013494395,61712384130914387513472,17705878041035105712624,13987908558573141976091,66711395857441041855197,0,66711395857441041855197 +79,deposit,0.3,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66710390004835519192334,4998005873921131668796,61712384130914387523539,17675107098470654812624,14021241891906475353115,66711588277532176889613,0,66711588277532176889613 +80,deposit,0.31666666666666665,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66710611500738869376747,4998227369824482037052,61712384130914387339697,17644336155906204212624,14054575225239808599067,66711778134645035937956,0,66711778134645035937956 +81,deposit,0.3333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66710829992880400779439,4998445861966013538003,61712384130914387241438,17613565213341753412624,14087908558573141976091,66711965437886287015153,0,66711965437886287015153 +82,deposit,0.35,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66711045491691802004882,4998661360777414645050,61712384130914387359833,17582794270777302412624,14121241891906475353115,66712150196216120232165,0,66712150196216120232165 +83,deposit,0.36666666666666664,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66711258007435851567824,4998873876521464175180,61712384130914387392645,17552023328212851612624,14154575225239808599067,66712332418449420481437,0,66712332418449420481437 +84,deposit,0.38333333333333336,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66711467550207743431254,4999083419293355942961,61712384130914387488295,17521252385648400512624,14187908558573142107163,66712512113256918361618,0,66712512113256918361618 +85,deposit,0.4,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66711674129936387471059,4999289999022000058281,61712384130914387412780,17490481443083949812624,14221241891906475353115,66712689289166319378270,0,66712689289166319378270 +86,deposit,0.4166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66711877756385685697002,4999493625471298057501,61712384130914387639503,17459710500519498712624,14254575225239808730139,66712863954563411858403,0,66712863954563411858403 +87,deposit,0.43333333333333335,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66712074733633309330128,4999690602718921788887,61712384130914387541243,17428939557955047912624,14287908558573142107163,66713032411460895916498,0,66713032411460895916498 +88,deposit,0.45,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66712249831737168455295,4999865700822781097897,61712384130914387357401,17398168615390597312624,14321241891906475353115,66713179425813409231973,0,66713179425813409231973 +89,deposit,0.4666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66712422005394367233537,5000037874479979866070,61712384130914387367468,17367397672826146412624,14354575225239808730139,66713323954739388790643,0,66713323954739388790643 +90,deposit,0.48333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66712591263707873186569,5000207132793485677962,61712384130914387508608,17336626730261695512624,14387908558573141976091,66713466006048440848674,0,66713466006048440848674 +91,deposit,0.5,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66712757615621772123875,5000373484707384605200,61712384130914387518676,17305855787697244612624,14421241891906475353115,66713605587413611407685,0,66713605587413611407685 +92,deposit,0.5166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66712921069922401046284,5000536939008013734196,61712384130914387312089,17275084845132793912624,14454575225239808730139,66713742706372368777307,0,66713742706372368777307 +93,deposit,0.5333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66713081635239458780673,5000697504325071327446,61712384130914387453228,17244313902568343012624,14487908558573141976091,66713877370327566485449,0,66713877370327566485449 +94,deposit,0.55,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66713239320047094411557,5000855189132706971009,61712384130914387440551,17213542960003892012624,14521241891906475484187,66714009586548387148293,0,66714009586548387148293 +95,deposit,0.5666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66713394132664973798873,5001010001750586194438,61712384130914387604436,17182772017439441212624,14554575225239808599067,66714139362171267319069,0,66714139362171267319069 +96,deposit,0.5833333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66713546081259324390052,5001161950344936906622,61712384130914387483431,17152001074874990312624,14587908558573142107163,66714266704200803093842,0,66714266704200803093842 +97,deposit,0.6,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66713695173843958885243,5001311042929571477328,61712384130914387407916,17121230132310539612624,14621241891906475353115,66714391619510637810415,0,66714391619510637810415 +98,deposit,0.6166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66713841418281277462014,5001457287366890066776,61712384130914387395239,17090459189746088612624,14654575225239808861211,66714514114844330913210,0,66714514114844330913210 +99,deposit,0.6333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66713984822283249245715,5001600691368861880502,61712384130914387365214,17059688247181638112624,14687908558573141845019,66714634196816208635477,0,66714634196816208635477 +100,deposit,0.65,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66714125393412373200943,5001741262497985740080,61712384130914387460864,17028917304617187012624,14721241891906475353115,66714751871912197025924,0,66714751871912197025924 +101,deposit,0.6666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66714263139082618311246,5001879008168230925899,61712384130914387385349,16998146362052736312624,14754575225239808599067,66714867146490636892386,0,66714867146490636892386 +102,deposit,0.6833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66714398066560343878822,5002013935645956397825,61712384130914387480999,16967375419488285212624,14787908558573142107163,66714980026783081518029,0,66714980026783081518029 +103,deposit,0.7,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66714530182965199419934,5002146052050812014451,61712384130914387405485,16936604476923834512624,14821241891906475353115,66715090518895076515827,0,66715090518895076515827 +104,deposit,0.7166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66714659495271005208008,5002275364356617769713,61712384130914387438297,16905833534359383712624,14854575225239808599067,66715198628806923143462,0,66715198628806923143462 +105,deposit,0.7333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66714786010306612785474,5002401879392225314367,61712384130914387471109,16875062591794932912624,14887908558573141845019,66715304362374423863335,0,66715304362374423863335 +106,deposit,0.75,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66714909734756746526714,5002525603842359068285,61712384130914387458432,16844291649230481912624,14921241891906475353115,66715407725329611795663,0,66715407725329611795663 +107,deposit,0.7666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715030675162825537372,5002646544248438091618,61712384130914387445755,16813520706666030912624,14954575225239808861211,66715508723281462830669,0,66715508723281462830669 +108,deposit,0.7833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715148837923767028572,5002764707009379615003,61712384130914387413571,16782749764101580172624,14987908558573142107163,66715607361716591895846,0,66715607361716591895846 +109,deposit,0.8,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715264229296770486092,5002880098382383083040,61712384130914387403053,16751978821537129412624,15021241891906475353115,66715703645999932314450,0,66715703645999932314450 +110,deposit,0.8166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715376855398083469505,5002992724483696076972,61712384130914387392534,16721207878972678652624,15054575225239808599067,66715797581375399363301,0,66715797581375399363301 +111,deposit,0.8333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715486722203748835711,5003102591289361412525,61712384130914387423188,16690436936408227612624,15087908558573142107163,66715889172966537657119,0,66715889172966537657119 +112,deposit,0.85,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715593835550333608360,5003209704635946206525,61712384130914387401837,16659665993843776862624,15121241891906475353115,66715978425777152702787,0,66715978425777152702787 +113,deposit,0.8666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715698201135640023668,5003314070221252645343,61712384130914387378327,16628895051279325872624,15154575225239808861211,66716065344691926770029,0,66716065344691926770029 +114,deposit,0.8833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715799824519398215233,5003415693605010801937,61712384130914387413298,16598124108714875312624,15187908558573141845019,66716149934477019057368,0,66716149934477019057368 +115,deposit,0.9,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715898711123941451076,5003514580209554050457,61712384130914387400621,16567353166150424312624,15221241891906475353115,66716232199780650562235,0,66716232199780650562235 +116,deposit,0.9166666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66715994866234863602945,5003610735320476212845,61712384130914387390102,16536582223585973552624,15254575225239808599067,66716312145133673620964,0,66716312145133673620964 +117,deposit,0.9333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66716088295001659041775,5003704164087271653518,61712384130914387388258,16505811281021522542624,15287908558573142107163,66716389774950126146244,0,66716389774950126146244 +118,deposit,0.95,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66716179002438345297959,5003794871523957898556,61712384130914387399405,16475040338457071762624,15321241891906475353115,66716465093527771010260,0,66716465093527771010260 +119,deposit,0.9666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66716266993424068573581,5003882862509681163030,61712384130914387410552,16444269395892620982624,15354575225239808599067,66716538105048620388093,0,66716538105048620388093 +120,deposit,0.9833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66716352272703691993252,5003968141789304586720,61712384130914387406533,16413498453328170216624,15387908558573141845019,66716608813579445267423,0,66716608813579445267423 +121,deposit,1.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712477623450614882106,63712384130914387398189,3000093492536227483918,16383178755753043729177,13421241891906475353115,66716434844888367187936,5004050713973979789748,61712384130914387398189,16382727510763719212624,15421241891906475353115,66716677223072270474825,0,66716677223072270474825 +122,deposit,0.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66693475012393794217663,4981090881479406470175,61712384130914387747490,22228183742027519815778,9146875968887923342743,66705774677316542829560,0,66705774677316542829560 +123,deposit,0.016666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66694391294989152024878,4982007164074764438920,61712384130914387585959,22197412799463069115778,9180209302221256674711,66706556846002908288497,0,66706556846002908288497 +124,deposit,0.03333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66695299637102074154924,4982915506187686838824,61712384130914387316101,22166641856898618515778,9213542635554590006679,66707332209047912580622,0,66707332209047912580622 +125,deposit,0.05,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66696200115970587545075,4983815985056200069620,61712384130914387475456,22135870914334167515778,9246875968887923342743,66708100833342079676448,0,66708100833342079676448 +126,deposit,0.06666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66697092807715903498582,4984708676801516180563,61712384130914387318021,22105099971769716815778,9280209302221256670615,66708862784800841068834,0,66708862784800841068834 +127,deposit,0.08333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66697977787361659455873,4985593656447271970306,61712384130914387485568,22074329029205265815778,9313542635554589998487,66709618128381491677495,0,66709618128381491677495 +128,deposit,0.1,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66698855128852756920156,4986470997938369391755,61712384130914387528403,22043558086640814915778,9346875968887923342743,66710366928099786356796,0,66710366928099786356796 +129,deposit,0.11666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66699724905073806030231,4987340774159418567320,61712384130914387462912,22012787144076364115778,9380209302221256686999,66711109247046187038958,0,66711109247046187038958 +130,deposit,0.13333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66700587187867185607630,4988203056952797960789,61712384130914387646843,21982016201511913115778,9413542635554589998487,66711845147401768345878,0,66711845147401768345878 +131,deposit,0.15,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66701442048050728283788,4989057917136340702439,61712384130914387581351,21951245258947462315778,9446875968887923342743,66712574690453789962103,0,66712574690453789962103 +132,deposit,0.16666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66702289555435039674865,4989905424520652234567,61712384130914387440300,21920474316383011615778,9480209302221256654231,66713297936610944114399,0,66713297936610944114399 +133,deposit,0.18333333333333332,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66703129778840460093708,4990745647926072794460,61712384130914387299249,21889703373818560915778,9513542635554589965719,66714014945418285814928,0,66714014945418285814928 +134,deposit,0.2,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66703962786113677686881,4991578655199290269239,61712384130914387417644,21858932431254109915778,9546875968887923342743,66714725775571853302185,0,66714725775571853302185 +135,deposit,0.21666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66704788644144000863510,4992404513229613327472,61712384130914387536039,21828161488689658915778,9580209302221256719767,66715430484932986517386,0,66715430484932986517386 +136,deposit,0.23333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66705607418879298496264,4993223287964910992950,61712384130914387503315,21797390546125208115778,9613542635554590031255,66716129130542350599916,0,66716129130542350599916 +137,deposit,0.25,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66706419175341615228745,4994035044427227758154,61712384130914387470592,21766619603560757315778,9646875968887923342743,66716821768633671177237,0,66716821768633671177237 +138,deposit,0.26666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66707223977642469983924,4994839846728082654384,61712384130914387329541,21735848660996306615778,9680209302221256654231,66717508454647188551730,0,66717508454647188551730 +139,deposit,0.2833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66708021888997844683407,4995637758083457169936,61712384130914387513472,21705077718431855615778,9713542635554589965719,66718189243242837501290,0,66718189243242837501290 +140,deposit,0.3,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66708803329570003931406,4996419198655616407868,61712384130914387523539,21674306775867404715778,9746875968887923342743,66718854526743324452902,0,66718854526743324452902 +141,deposit,0.31666666666666665,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66709564935161964789730,4997180804247577450034,61712384130914387339697,21643535833302954115778,9780209302221256588695,66719500926485219354408,0,66719500926485219354408 +142,deposit,0.3333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66710319837131415603125,4997935706217028361689,61712384130914387241438,21612764890738503315778,9813542635554589965719,66720141592193413063781,0,66720141592193413063781 +143,deposit,0.35,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66711068095204049479008,4998683964289662119177,61712384130914387359833,21581993948174052315778,9846875968887923342743,66720776575467020592213,0,66720776575467020592213 +144,deposit,0.36666666666666664,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66711809768281511264526,4999425637367123871883,61712384130914387392645,21551223005609601515778,9880209302221256588695,66721405927187968333748,0,66721405927187968333748 +145,deposit,0.38333333333333336,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66712544914454653490476,5000160783540266002182,61712384130914387488295,21520452063045150415778,9913542635554590096791,66722029697532632844648,0,66722029697532632844648 +146,deposit,0.4,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66713273591016529585561,5000889460102142172782,61712384130914387412780,21489681120480699715778,9946875968887923342743,66722647935983247010789,0,66722647935983247010789 +147,deposit,0.4166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66713995854475130863034,5001611723560743223532,61712384130914387639503,21458910177916248615778,9980209302221256719767,66723260691339079285922,0,66723260691339079285922 +148,deposit,0.43333333333333335,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66714711760565872655008,5002327629651485113766,61712384130914387541243,21428139235351797815778,10013542635554590096791,66723868011727391343129,0,66723868011727391343129 +149,deposit,0.45,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66715421364263835569294,5003037233349448211894,61712384130914387357401,21397368292787347215778,10046875968887923342743,66724469944614178809538,0,66724469944614178809538 +150,deposit,0.4666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66716124719795767214669,5003740588881379847203,61712384130914387367468,21366597350222896315778,10080209302221256719767,66725066536814700370767,0,66725066536814700370767 +151,deposit,0.48333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66716821880651849640579,5004437749737462131972,61712384130914387508608,21335826407658445415778,10113542635554589965719,66725657834503799689302,0,66725657834503799689302 +152,deposit,0.5,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66717512899597238327033,5005128768682850808359,61712384130914387518676,21305055465093994515778,10146875968887923342743,66726243883226025189724,0,66726243883226025189724 +153,deposit,0.5166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66718197828683376900278,5005813697768989588190,61712384130914387312089,21274284522529543815778,10180209302221256719767,66726824727905551848128,0,66726824727905551848128 +154,deposit,0.5333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66718876719259093357925,5006492588344705904698,61712384130914387453228,21243513579965092915778,10213542635554589965719,66727400412855909887950,0,66727400412855909887950 +155,deposit,0.55,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66719549621981482295863,5007165491067094855315,61712384130914387440551,21212742637400641915778,10246875968887923473815,66727970981789524122243,0,66727970981789524122243 +156,deposit,0.5666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66720216586826577754931,5007832455912190150496,61712384130914387604436,21181971694836191115778,10280209302221256588695,66728536477827068769883,0,66728536477827068769883 +157,deposit,0.5833333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66720877663099821624823,5008493532185434141394,61712384130914387483431,21151200752271740215778,10313542635554590096791,66729096943506641223233,0,66729096943506641223233 +158,deposit,0.6,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66721532899446331645971,5009148768531944238056,61712384130914387407916,21120429809707289515778,10346875968887923342743,66729652420792759317602,0,66729652420792759317602 +159,deposit,0.6166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66722182343860974030922,5009798212946586635685,61712384130914387395239,21089658867142838515778,10380209302221256850839,66730202951085185768667,0,66730202951085185768667 +160,deposit,0.6333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66722826043698244009863,5010441912783856644650,61712384130914387365214,21058887924578388015778,10413542635554589834647,66730748575227583214728,0,66730748575227583214728 +161,deposit,0.65,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66723464045681959608665,5011079914767572147803,61712384130914387460864,21028116982013936915778,10446875968887923342743,66731289333516004380882,0,66731289333516004380882 +162,deposit,0.6666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66724096395914771621394,5011712265000384236047,61712384130914387385349,20997346039449486215778,10480209302221256588695,66731825265707219995709,0,66731825265707219995709 +163,deposit,0.6833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66724723139887494609438,5012339008973107128440,61712384130914387480999,20966575096885035115778,10513542635554590096791,66732356411026888967621,0,66732356411026888967621 +164,deposit,0.7,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66725344322488262104302,5012960191573874698818,61712384130914387405485,20935804154320584415778,10546875968887923342743,66732882808177573315906,0,66732882808177573315906 +165,deposit,0.7166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66725959988011510288874,5013575857097122850578,61712384130914387438297,20905033211756133615778,10580209302221256588695,66733404495346601963193,0,66733404495346601963193 +166,deposit,0.7333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66726570180166793476920,5014186049252406005813,61712384130914387471109,20874262269191682815778,10613542635554589834647,66733921510213786067975,0,66733921510213786067975 +167,deposit,0.75,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66727174942087435072447,5014790811173047614017,61712384130914387458432,20843491326627231815778,10646875968887923342743,66734433889958989435329,0,66734433889958989435329 +168,deposit,0.7666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66727774316339017612682,5015390185424630166928,61712384130914387445755,20812720384062780815778,10680209302221256850839,66734941671269557059116,0,66734941671269557059116 +169,deposit,0.7833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66728368344927715177324,5015984214013327763754,61712384130914387413571,20781949441498330075778,10713542635554590096791,66735444890347604689389,0,66735444890347604689389 +170,deposit,0.8,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66728957069308471405172,5016572938394084002120,61712384130914387403053,20751178498933879315778,10746875968887923342743,66735943582917172345544,0,66735943582917172345544 +171,deposit,0.8166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66729540530393026639193,5017156399478639246661,61712384130914387392534,20720407556369428555778,10780209302221256588695,66736437784231244979475,0,66736437784231244979475 +172,deposit,0.8333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66730118768557796967867,5017734637643409544680,61712384130914387423188,20689636613804977515778,10813542635554590096791,66736927529078642638904,0,66736927529078642638904 +173,deposit,0.85,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66730691823651608631646,5018307692737221229810,61712384130914387401837,20658865671240526765778,10846875968887923342743,66737412851790783167271,0,66737412851790783167271 +174,deposit,0.8666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66731259735003290559636,5018875604088903181310,61712384130914387378327,20628094728676075775778,10880209302221256850839,66737893786248320143816,0,66737893786248320143816 +175,deposit,0.8833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66731822541429128037375,5019438410514740624079,61712384130914387413298,20597323786111625215778,10913542635554589834647,66738370365887658336982,0,66738370365887658336982 +176,deposit,0.9,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66732380281240180444498,5019996150325793043878,61712384130914387400621,20566552843547174215778,10946875968887923342743,66738842623707349738064,0,66738842623707349738064 +177,deposit,0.9166666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66732932992249465772273,5020548861335078382173,61712384130914387390102,20535781900982723455778,10980209302221256588695,66739310592274372133390,0,66739310592274372133390 +178,deposit,0.9333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66733480711779014574397,5021096580864627186140,61712384130914387388258,20505010958418272445778,11013542635554590096791,66739774303730292935808,0,66739774303730292935808 +179,deposit,0.95,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66734023476666796351078,5021639345752408951674,61712384130914387399405,20474240015853821665778,11046875968887923342743,66740233789797320617029,0,66740233789797320617029 +180,deposit,0.9666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66734561323273520484283,5022177192359133073733,61712384130914387410552,20443469073289370885778,11080209302221256588695,66740689081784245881370,0,66740689081784245881370 +181,deposit,0.9833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66735094287489314776804,5022710156574927370273,61712384130914387406533,20412698130724920119778,11113542635554589834647,66741140210592275245947,0,66741140210592275245947 +182,deposit,1.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712642485476159786010,63712384130914387398189,3000258354561772387822,20383178755753043729177,9146875968887923342743,66735622404740283701992,5023238273825896303804,61712384130914387398189,20381927188160469115778,11146875968887923342743,66741587206720758574325,0,66741587206720758574325 +183,deposit,0.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715963100705935876081,5003578969791548128592,61712384130914387747490,14388622837651922410322,17580468926380907034023,66716140971774673918504,0,66716140971774673918504 +184,deposit,0.016666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715893949046974053944,5003509818132586467987,61712384130914387585959,14357851895087471710322,17613802259714240365991,66716083958099123387351,0,66716083958099123387351 +185,deposit,0.03333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715822111222543494562,5003437980308156178462,61712384130914387316101,14327080952523021110322,17647135593047573697959,66716024663266964013442,0,66716024663266964013442 +186,deposit,0.05,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715747583279380780651,5003363452364993305197,61712384130914387475456,14296310009958570110322,17680468926380907034023,66715963083890621540616,0,66715963083890621540616 +187,deposit,0.06666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715670361133099450054,5003286230218712132034,61712384130914387318021,14265539067394119410322,17713802259714240361895,66715899216470014467964,0,66715899216470014467964 +188,deposit,0.08333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715590440567700814761,5003206309653313329195,61712384130914387485568,14234768124829668410322,17747135593047573689767,66715833057392130350814,0,66715833057392130350814 +189,deposit,0.1,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715507817235068758112,5003123686320681229711,61712384130914387528403,14203997182265217510322,17780468926380907034023,66715764602930588507677,0,66715764602930588507677 +190,deposit,0.11666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715422486654447946331,5003038355740060483420,61712384130914387462912,14173226239700766710322,17813802259714240378279,66715693849245188012482,0,66715693849245188012482 +191,deposit,0.13333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715334444211905343074,5002950313297517696232,61712384130914387646843,14142455297136315710322,17847135593047573689767,66715620792381441488948,0,66715620792381441488948 +192,deposit,0.15,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715243685159775340698,5002859554245387759348,61712384130914387581351,14111684354571864910322,17880468926380907034023,66715545428270094627179,0,66715545428270094627179 +193,deposit,0.16666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715150204616087873137,5002766073701700432838,61712384130914387440300,14080913412007414210322,17913802259714240345511,66715467752726630735983,0,66715467752726630735983 +194,deposit,0.18333333333333332,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66715053997563979646089,5002669866649592346842,61712384130914387299249,14050142469442963510322,17947135593047573656999,66715387761450761036798,0,66715387761450761036798 +195,deposit,0.2,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714955058851088326499,5002570927936700908856,61712384130914387417644,14019371526878512510322,17980468926380907034023,66715305450025899765828,0,66715305450025899765828 +196,deposit,0.21666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714853383188929503418,5002469252274541967380,61712384130914387536039,13988600584314061510322,18013802259714240411047,66715220813918624609033,0,66715220813918624609033 +197,deposit,0.23333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714748965152256311416,5002364834237868808102,61712384130914387503315,13957829641749610710322,18047135593047573722535,66715133848478122080859,0,66715133848478122080859 +198,deposit,0.25,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714641799178401565029,5002257668264014094438,61712384130914387470592,13927058699185159910322,18080468926380907034023,66715044548935617477080,0,66715044548935617477080 +199,deposit,0.26666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714531879566602242706,5002147748652214913167,61712384130914387329541,13896287756620709210322,18113802259714240345511,66714952910403789857760,0,66714952910403789857760 +200,deposit,0.2833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714419200477306164663,5002035069562918651192,61712384130914387513472,13865516814056258210322,18147135593047573656999,66714858927876171371615,0,66714858927876171371615 +201,deposit,0.3,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714303755931460683328,5001919625017073159790,61712384130914387523539,13834745871491807310322,18180468926380907034023,66714762596226530917368,0,66714762596226530917368 +202,deposit,0.31666666666666665,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714185539809783395360,5001801408895396055664,61712384130914387339697,13803974928927356710322,18213802259714240279975,66714663910208242477090,0,66714663910208242477090 +203,deposit,0.3333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66714064545852014373651,5001680414937627132214,61712384130914387241438,13773203986362905910322,18247135593047573656999,66714562864453637041228,0,66714562864453637041228 +204,deposit,0.35,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66713940767656150039114,5001556636741762679282,61712384130914387359833,13742433043798454910322,18280468926380907034023,66714459453473339015355,0,66714459453473339015355 +205,deposit,0.36666666666666664,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66713814198677658439934,5001430067763271047290,61712384130914387392645,13711662101234004110322,18313802259714240279975,66714353671655585982731,0,66714353671655585982731 +206,deposit,0.38333333333333336,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66713684832228675603286,5001300701314288114993,61712384130914387488295,13680891158669553010322,18347135593047573788071,66714245513265532544153,0,66714245513265532544153 +207,deposit,0.4,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66713552661477182882961,5001168530562795470183,61712384130914387412780,13650120216105102310322,18380468926380907034023,66714134972444537276903,0,66714134972444537276903 +208,deposit,0.4166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66713417679446165308802,5001033548531777669301,61712384130914387639503,13619349273540651210322,18413802259714240411047,66714022043209433482634,0,66714022043209433482634 +209,deposit,0.43333333333333335,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66713279879012750251000,5000895748098362709758,61712384130914387541243,13588578330976200410322,18447135593047573788071,66713906719451782582307,0,66713906719451782582307 +210,deposit,0.45,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66713139252907326656010,5000755121992939298610,61712384130914387357401,13557807388411749810322,18480468926380907034023,66713788994937110783525,0,66713788994937110783525 +211,deposit,0.4666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66712995793712644504817,5000611662798257137351,61712384130914387367468,13527036445847298910322,18513802259714240411047,66713668863304128549652,0,66713668863304128549652 +212,deposit,0.48333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66712849493862894175195,5000465362948506666589,61712384130914387508608,13496265503282848010322,18547135593047573656999,66713546318063932701553,0,66713546318063932701553 +213,deposit,0.5,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66712700345642765548743,5000316214728378030068,61712384130914387518676,13465494560718397110322,18580468926380907034023,66713421352599190723552,0,66713421352599190723552 +214,deposit,0.5166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66712548341186486884770,5000164210272099572683,61712384130914387312089,13434723618153946410322,18613802259714240411047,66713293960163307622125,0,66713293960163307622125 +215,deposit,0.5333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66712393472476842618805,5000009341562455165579,61712384130914387453228,13403952675589495510322,18647135593047573656999,66713164133879574393265,0,66713164133879574393265 +216,deposit,0.55,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66712235731344170743684,4999851600429783303134,61712384130914387440551,13373181733025044510322,18680468926380907165095,66713031866740299042034,0,66713031866740299042034 +217,deposit,0.5666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66712071578109851270917,4999687447195463666482,61712384130914387604436,13342410790460593710322,18713802259714240279975,66712893619669810444519,0,66712893619669810444519 +218,deposit,0.5833333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66711885416649006628920,4999501285734619145491,61712384130914387483431,13311639847896142810322,18747135593047573788071,66712733795047557219686,0,66712733795047557219686 +219,deposit,0.6,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66711696356828430504775,4999312225914043096860,61712384130914387407916,13280868905331692110322,18780468926380907034023,66712571507005846413047,0,66712571507005846413047 +220,deposit,0.6166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66711504389845100687112,4999120258930713291874,61712384130914387395239,13250097962767241110322,18813802259714240542119,66712406747984893968700,0,66712406747984893968700 +221,deposit,0.6333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66711309506738108953539,4998925375823721588327,61712384130914387365214,13219327020202790610322,18847135593047573525927,66712239510289177275721,0,66712239510289177275721 +222,deposit,0.65,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66711111698387525259133,4998727567473137798271,61712384130914387460864,13188556077638339510322,18880468926380907034023,66712069786086449078924,0,66712069786086449078924 +223,deposit,0.6666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66710910955513238804586,4998526824598851419238,61712384130914387385349,13157785135073888810322,18913802259714240279975,66711897567406731516092,0,66711897567406731516092 +224,deposit,0.6833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66710707268673776426178,4998323137759388945181,61712384130914387480999,13127014192509437710322,18947135593047573788071,66711722846141290540303,0,66711722846141290540303 +225,deposit,0.7,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66710500628265097486256,4998116497350710080773,61712384130914387405485,13096243249944987010322,18980468926380907034023,66711545614041589562116,0,66711545614041589562116 +226,deposit,0.7166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66710291024519365190566,4997906893604977752270,61712384130914387438297,13065472307380536210322,19013802259714240279975,66711365862718222838145,0,66711365862718222838145 +227,deposit,0.7333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66710078447503694063220,4997694316589306592113,61712384130914387471109,13034701364816085410322,19047135593047573525927,66711183583639828020456,0,66711183583639828020456 +228,deposit,0.75,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66709862887118873217899,4997478756204485759469,61712384130914387458432,13003930422251634410322,19080468926380907034023,66710998768131977757245,0,66710998768131977757245 +229,deposit,0.7666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66709644333098065098546,4997260202183677652793,61712384130914387445755,12973159479687183410322,19113802259714240542119,66710811407376049641294,0,66710811407376049641294 +230,deposit,0.7833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66709422775005479290060,4997038644091091876491,61712384130914387413571,12942388537122732670322,19147135593047573788071,66710621492408074774998,0,66710621492408074774998 +231,deposit,0.8,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66709198202235021404046,4996814071320634000995,61712384130914387403053,12911617594558281910322,19180468926380907034023,66710429014117564485194,0,66710429014117564485194 +232,deposit,0.8166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66708970604008916168849,4996586473094528776316,61712384130914387392534,12880846651993831150322,19213802259714240279975,66710233963246314571110,0,66710233963246314571110 +233,deposit,0.8333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66708739969376304846325,4996355838461917423138,61712384130914387423188,12850075709429380110322,19247135593047573788071,66710036330387187243359,0,66710036330387187243359 +234,deposit,0.85,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66708506287211816516108,4996122156297429114273,61712384130914387401837,12819304766864929360322,19280468926380907034023,66709836105982870234999,0,66709836105982870234999 +235,deposit,0.8666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66708269546214112597196,4995885415299725218870,61712384130914387378327,12788533824300478370322,19313802259714240542119,66709633280324612634180,0,66709633280324612634180 +236,deposit,0.8833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66708029734904404696341,4995645603990017283045,61712384130914387413298,12757762881736027810322,19347135593047573525927,66709427843550937583021,0,66709427843550937583021 +237,deposit,0.9,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66707786841624944934164,4995402710710557533545,61712384130914387400621,12726991939171576810322,19380468926380907034023,66709219785646330825343,0,66709219785646330825343 +238,deposit,0.9166666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66707540854537488763671,4995156723623101373571,61712384130914387390102,12696220996607126050322,19413802259714240279975,66709009096439905235030,0,66709009096439905235030 +239,deposit,0.9333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66707291761621729684549,4994907630707342296293,61712384130914387388258,12665450054042675040322,19447135593047573788071,66708795765604041219657,0,66708795765604041219657 +240,deposit,0.95,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66707039550673705496430,4994655419759318097027,61712384130914387399405,12634679111478224260322,19480468926380907034023,66708579782653001922090,0,66708579782653001922090 +241,deposit,0.9666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66706784209304175621223,4994400078389788210673,61712384130914387410552,12603908168913773480322,19513802259714240279975,66708361136941523333073,0,66708361136941523333073 +242,deposit,0.9833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66706525724936969228314,4994141594022581821782,61712384130914387406533,12573137226349322714322,19547135593047573525927,66708139817663378990176,0,66708139817663378990176 +243,deposit,1.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712471242254478643742,63712384130914387398189,3000087111340091245555,12542366283784871710322,17580924427536831499051,66706264084807303585446,4993879953892916187258,61712384130914387398189,12542366283784871710322,19580468926380907034023,66707915813849918817376,0,66707915813849918817376 +244,deposit,0.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66732292563355818310017,5019908432441430562528,61712384130914387747490,10741089325333836848652,21579668616355182502545,66737128878078880195313,0,66737128878078880195313 +245,deposit,0.016666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66731832231874835187820,5019448100960447601862,61712384130914387585959,10710318382769386148652,21613001949688515834513,66736739523624500731933,0,66736739523624500731933 +246,deposit,0.03333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66731367525400959480812,5018983394486572164713,61712384130914387316101,10679547440204935548652,21646335283021849166481,66736346441446460614850,0,66736346441446460614850 +247,deposit,0.05,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66730898414653512263867,5018514283739124788413,61712384130914387475456,10648776497640484548652,21679668616355182502545,66735949606355194132197,0,66735949606355194132197 +248,deposit,0.06666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66730424869971791048012,5018040739057403729993,61712384130914387318021,10618005555076033848652,21713001949688515830417,66735548992832476176496,0,66735548992832476176496 +249,deposit,0.08333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66729946861310025981437,5017562730395638495870,61712384130914387485568,10587234612511582848652,21746335283021849158289,66735144575027023564185,0,66735144575027023564185 +250,deposit,0.1,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66729464358232246481986,5017080227317858953585,61712384130914387528403,10556463669947131948652,21779668616355182502545,66734736326750017647970,0,66734736326750017647970 +251,deposit,0.11666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66728977329907056494301,5016593198992669031391,61712384130914387462912,10525692727382681148652,21813001949688515846801,66734324221470547018488,0,66734324221470547018488 +252,deposit,0.13333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66728485745102316497586,5016101614187928850745,61712384130914387646843,10494921784818230148652,21846335283021849158289,66733908232310967865932,0,66733908232310967865932 +253,deposit,0.15,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66727989572179730298410,5015605441265342717061,61712384130914387581351,10464150842253779348652,21879668616355182502545,66733488332042181256261,0,66733488332042181256261 +254,deposit,0.16666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66727488779089334932601,5015104648174947492303,61712384130914387440300,10433379899689328648652,21913001949688515814033,66733064493078824868115,0,66733064493078824868115 +255,deposit,0.18333333333333332,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66726983333363891842940,5014599202449504543693,61712384130914387299249,10402608957124877948652,21946335283021849125521,66732636687474378310957,0,66732636687474378310957 +256,deposit,0.2,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66726473202113176813797,5014089071198789396154,61712384130914387417644,10371838014560426948652,21979668616355182502545,66732204886916179324007,0,66732204886916179324007 +257,deposit,0.21666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66725958352018167311716,5013574221103779775678,61712384130914387536039,10341067071995975948652,22013001949688515879569,66731769062720349923017,0,66731769062720349923017 +258,deposit,0.23333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66725438749325124811092,5013054618410737307778,61712384130914387503315,10310296129431525148652,22046335283021849191057,66731329185826630208470,0,66731329185826630208470 +259,deposit,0.25,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66724914359839569803099,5012530228925182332508,61712384130914387470592,10279525186867074348652,22079668616355182502545,66730885226793117873383,0,66730885226793117873383 +260,deposit,0.26666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66724385148920147851606,5012001018005760522066,61712384130914387329541,10248754244302623648652,22113001949688515814033,66730437155790912007778,0,66730437155790912007778 +261,deposit,0.2833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66723851081472383886795,5011466950557996373324,61712384130914387513472,10217983301738172648652,22146335283021849125521,66729984942598658480848,0,66729984942598658480848 +262,deposit,0.3,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66723312121942322944024,5010927991027935420487,61712384130914387523539,10187212359173721748652,22179668616355182502545,66729528556596995606366,0,66729528556596995606366 +263,deposit,0.31666666666666665,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66722768234310054781294,5010384103395667441599,61712384130914387339697,10156441416609271148652,22213001949688515748497,66729067966762897629149,0,66729067966762897629149 +264,deposit,0.3333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66722219382083119768787,5009835251168732527350,61712384130914387241438,10125670474044820348652,22246335283021849125521,66728603141663913794796,0,66728603141663913794796 +265,deposit,0.35,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66721665528289794348409,5009281397375406988578,61712384130914387359833,10094899531480369348652,22279668616355182502545,66728134049452301467312,0,66728134049452301467312 +266,deposit,0.36666666666666664,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66721106635472252570201,5008722504557865177559,61712384130914387392645,10064128588915918548652,22313001949688515748497,66727660657859050206770,0,66727660657859050206770 +267,deposit,0.38333333333333336,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66720542665679601907164,5008158534765214418871,61712384130914387488295,10033357646351467448652,22346335283021849256593,66727182934187795169836,0,66727182934187795169836 +268,deposit,0.4,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66719973580460790526115,5007589449546403113336,61712384130914387412780,10002586703787016748652,22379668616355182502545,66726700845308617416223,0,66726700845308617416223 +269,deposit,0.4166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66719399340857383136370,5007015209942995496868,61712384130914387639503,9971815761222565648652,22413001949688515879569,66726214357651728598076,0,66726214357651728598076 +270,deposit,0.43333333333333335,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66718819907396202680137,5006435776481815138896,61712384130914387541243,9941044818658114848652,22446335283021849256593,66725723437201037301139,0,66725723437201037301139 +271,deposit,0.45,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66718235240081835578286,5005851109167448220886,61712384130914387357401,9910273876093664248652,22479668616355182502545,66725228049487595495734,0,66725228049487595495734 +272,deposit,0.4666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66717645298388996655419,5005261167474609287952,61712384130914387367468,9879502933529213348652,22513001949688515879569,66724728159582921180963,0,66724728159582921180963 +273,deposit,0.48333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66717050041254751877195,5004665910340364368588,61712384130914387508608,9848731990964762448652,22546335283021849125521,66724223732092195952109,0,66724223732092195952109 +274,deposit,0.5,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66716449427070595004917,5004065296156207486243,61712384130914387518676,9817961048400311548652,22579668616355182502545,66723714731147333773835,0,66723714731147333773835 +275,deposit,0.5166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66715843413674375523478,5003459282759988211390,61712384130914387312089,9787190105835860848652,22613001949688515879569,66723201120399918651410,0,66723201120399918651410 +276,deposit,0.5333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66715231958342074477529,5002847827427687024302,61712384130914387453228,9756419163271409948652,22646335283021849125521,66722682863014008328247,0,66722682863014008328247 +277,deposit,0.55,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66714615017779425102102,5002230886865037661553,61712384130914387440551,9725648220706958948652,22679668616355182633617,66722159921658801237465,0,66722159921658801237465 +278,deposit,0.5666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66713992548113374688578,5001608417198987084144,61712384130914387604436,9694877278142508148652,22713001949688515748497,66721632258501163331290,0,66721632258501163331290 +279,deposit,0.5833333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66713364504883384448822,5000980373968996965393,61712384130914387483431,9664106335578057248652,22746335283021849256593,66721099835198012117317,0,66721099835198012117317 +280,deposit,0.6,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66712730843032563713105,5000346712118176305191,61712384130914387407916,9633335393013606548652,22779668616355182502545,66720562612888554647505,0,66720562612888554647505 +281,deposit,0.6166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66712091516898635012964,4999707385984247617727,61712384130914387395239,9602564450449155548652,22813001949688516010641,66720020552186376246887,0,66720020552186376246887 +282,deposit,0.6333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66711446480204726308689,4999062349290338943477,61712384130914387365214,9571793507884705048652,22846335283021848994449,66719473613171376776381,0,66719473613171376776381 +283,deposit,0.65,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66710795686049986303393,4998411555135598842531,61712384130914387460864,9541022565320253948652,22879668616355182502545,66718921755381550840369,0,66718921755381550840369 +284,deposit,0.6666666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66710139086900019506686,4997754955985632121338,61712384130914387385349,9510251622755803248652,22913001949688515748497,66718364937804608755440,0,66718364937804608755440 +285,deposit,0.6833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66709476634577136578934,4997092503662749097937,61712384130914387480999,9479480680191352148652,22946335283021849256593,66717803118869434716283,0,66717803118869434716283 +286,deposit,0.7,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66708796457332283847126,4996412326417896441643,61712384130914387405485,9448709737626901448652,22979668616355182502545,66717224413576328846473,0,66717224413576328846473 +287,deposit,0.7166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66708099450194925560922,4995715319280538122626,61712384130914387438297,9417938795062450648652,23013001949688515748497,66716629724611977940826,0,66716629724611977940826 +288,deposit,0.7333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66707396438852726099226,4995012307938338628119,61712384130914387471109,9387167852497999848652,23046335283021848994449,66716029902641003760584,0,66716029902641003760584 +289,deposit,0.75,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66706687372408171314015,4994303241493783855585,61712384130914387458432,9356396909933548848652,23079668616355182502545,66715424903710083737021,0,66715424903710083737021 +290,deposit,0.7666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66705972199267989114982,4993588068353601669229,61712384130914387445755,9325625967369097848652,23113001949688516010641,66714814683260832057510,0,66714814683260832057510 +291,deposit,0.7833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66705250867132185823073,4992866736217798409504,61712384130914387413571,9294855024804647108652,23146335283021849256593,66714199196120180809294,0,66714199196120180809294 +292,deposit,0.8,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66704523322982866595386,4992139192068479192334,61712384130914387403053,9264084082240196348652,23179668616355182502545,66713578396490569910081,0,66713578396490569910081 +293,deposit,0.8166666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66703789513072835350504,4991405382158447957972,61712384130914387392534,9233313139675745588652,23213001949688515748497,66712952237939942119450,0,66712952237939942119450 +294,deposit,0.8333333333333334,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66703049382913968523755,4990665251999581100568,61712384130914387423188,9202542197111294548652,23246335283021849256593,66712320673391538007479,0,66712320673391538007479 +295,deposit,0.85,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66702302877265358385872,4989918746350970984037,61712384130914387401837,9171771254546843798652,23279668616355182502545,66711683655113487006724,0,66711683655113487006724 +296,deposit,0.8666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66701549940121219607946,4989165809206832229621,61712384130914387378327,9141000311982392808652,23313001949688516010641,66711041134708188947236,0,66711041134708188947236 +297,deposit,0.8833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66700790514698554674255,4988406383784167260958,61712384130914387413298,9110229369417942248652,23346335283021848994449,66710393063101481968849,0,66710393063101481968849 +298,deposit,0.9,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66700024543424571700330,4987640412510184299711,61712384130914387400621,9079458426853491248652,23379668616355182502545,66709739390531591639601,0,66709739390531591639601 +299,deposit,0.9166666666666666,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66699251967923849557741,4986867837009462167641,61712384130914387390102,9048687484289040488652,23413001949688515748497,66709080066537855864765,0,66709080066537855864765 +300,deposit,0.9333333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66698472729005243998693,4986088598090856610436,61712384130914387388258,9017916541724589478652,23446335283021849256593,66708415039949220599372,0,66708415039949220599372 +301,deposit,0.95,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66697686766648529118424,4985302635734141719020,61712384130914387399405,8987145599160138698652,23479668616355182502545,66707744258872501265586,0,66707744258872501265586 +302,deposit,0.9666666666666667,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66696894019990767541759,4984509889076380131208,61712384130914387410552,8956374656595687918652,23513001949688515748497,66707067670680403444977,0,66707067670680403444977 +303,deposit,0.9833333333333333,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66696094427312403375002,4983710296398015968470,61712384130914387406533,8925603714031237152652,23546335283021848994449,66706385221999298368652,0,66706385221999298368652 +304,deposit,1.0,66712384130914387325786,66712384130914387325786,0,66712383751034226541732,14127626670428115429177,15857742858560606821195,66712623623253949942934,63712384130914387398189,3000239492339562544746,8894832771466786148652,21580924427536831499051,66695287926023071098824,4982903795108683700636,61712384130914387398189,8894832771466786148652,23579668616355182502545,66705696858696746149030,0,66705696858696746149030 diff --git a/brownie/balancer_test/strategy_harness.py b/brownie/balancer_test/strategy_harness.py new file mode 100644 index 0000000000..bc2615373f --- /dev/null +++ b/brownie/balancer_test/strategy_harness.py @@ -0,0 +1,299 @@ +# Tilt Tester +from world import * +from brownie import chain +import random +import pandas as pd + +WSTETH_WHALE = "0x176f3dab24a159341c0509bb36b833e7fdd0a132" +WETH_WHALE = "0x8EB8a3b98659Cce290402893d0123abb75E3ab28" +WETH_WHALE2 = "0xf04a5cc80b1e94c69b48f5ee68a08cd2f09a7c3e" +RETH_WHALE = "0xCc9EE9483f662091a1de4795249E24aC0aC2630f" +RETH_WHALE2 = "0xC6424e862f1462281B0a5FAc078e4b63006bDEBF" +strat_address = "0x85094b52754591A3dE0002AD97F433584389aea0" + +do_it_fast = False + +class BalancerRethEth: + def __init__(self): + pool_address = "0x1E19CF2D73a72Ef1332C882F20534B6519Be0276" + self.strat = load_contract("balancer_strat", strat_address) + self.pool = load_contract("balancer_metastablepool", pool_address) + self.name = "Balancer Steth-Eth Metastable" + self.vault_core = oeth_vault_core + self.vault_admin = oeth_vault_admin + self.base_size = 2000 + + self.strat.setMaxDepositDeviation(1e18, {'from': STRATEGIST}) # == 100% + self.strat.setMaxWithdrawalDeviation(4 * 1e18, {'from': STRATEGIST}) # == 100% + self._balancer_vault = load_contract("balancer_vault", self.pool.getVault()) + self._pool_pid = "0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112" + self._pool_tokens = self.pool_balances().keys() + self.rethExchangeRate = reth.getExchangeRate() + + reth.approve(self._balancer_vault, 1e70, {'from': RETH_WHALE}) + weth.approve(self._balancer_vault, 1e70, {'from': WETH_WHALE}) + + def pool_balances(self): + balances = self._balancer_vault.getPoolTokens(self._pool_pid)[0:2] + return dict(zip(balances[0], balances[1])) + + def to_reth_amount(self, amount): + return amount * 1e18 / self.rethExchangeRate + + def from_reth_to_units(self, amount): + return amount * self.rethExchangeRate / 1e18 + + # put the pool to exact 50%/50% share + def balance_pool(self): + (reth_balance, weth_balance) = list(harness.pool_balances().values()) + reth_unit_balance = self.from_reth_to_units(reth_balance) + + if reth_unit_balance > weth_balance: + # convert from unit amount to reth amoount + weth_amount = (reth_unit_balance - weth_balance) / 2 + # swapping WETH specified by amount for RETH + self._balancer_vault.swap((self._pool_pid, 0, WETH, RETH, weth_amount, ""), (WETH_WHALE, False, WETH_WHALE, False), 1, chain.time()+100, {"from": WETH_WHALE}) + else: + to_reth_amount = self.to_reth_amount(weth_balance - reth_unit_balance) / 2 + # swapping RETH specified by amount for WETH + self._balancer_vault.swap((self._pool_pid, 0, RETH, WETH, to_reth_amount, ""), (RETH_WHALE, False, RETH_WHALE, False), 1, chain.time()+100, {"from": RETH_WHALE}) + + def tilt_pool(self, size): + self.balance_pool() + amount = abs(size) * self.base_size * int(1e18) + if size == 0: + pass + elif size > 0: + # swapping WETH specified by amount for RETH + self._balancer_vault.swap((self._pool_pid, 0, WETH, RETH, amount, ""), (WETH_WHALE, False, WETH_WHALE, False), 1, chain.time()+100, {"from": WETH_WHALE}) + else: + # swapping RETH specified by amount for WETH + self._balancer_vault.swap((self._pool_pid, 0, RETH, WETH, self.to_reth_amount(amount), ""), (RETH_WHALE, False, RETH_WHALE, False), 1, chain.time()+100, {"from": RETH_WHALE}) + + def pool_create_mix(self, tilt=0.5, size=1): + return { + # account for rethExchangeRate + RETH: self.to_reth_amount(int(size * self.base_size * (int(1e18)-(int(1e18) * tilt)))), + WETH: int(size * self.base_size * int(1e18) * tilt), + } + +harness = BalancerRethEth() + +# Run setup +try: + harness.vault_admin.withdrawAllFromStrategies({'from':STRATEGIST}) +except: + print("Withdraw all failed") + +harness.vault_admin.withdrawAllFromStrategy(harness.strat, {'from':STRATEGIST}) +if (weth.balanceOf(harness.vault_admin) < 2e4 * int(1e18)): + weth.transfer(harness.vault_admin, 2e4 * int(1e18), {'from': WETH_WHALE2}) +if (reth.balanceOf(harness.vault_admin) < 2e4 * int(1e18)): + reth.transfer(harness.vault_admin, 2e4 * int(1e18), {'from': RETH_WHALE2}) + +# Test Deposits + +deposit_stats = [] +steps = 20 if do_it_fast else 60 +for initial_tilt in [0.0, -1, -3, 1, 3]: +#for initial_tilt in [0.0]: + for deposit_x in range (0, steps + 1, 1): + #for deposit_mix in [0.4, 0.45]: + with TemporaryFork(): + stat = {} + + deposit_mix = deposit_x / steps + + stat['action'] = 'deposit' + stat['action_mix'] = deposit_mix + + stat['start_vault'] = harness.vault_core.totalValue() + stat['start_value_in_vault'] = harness.vault_core.totalValueInVault() + stat['start_strat_check_balance'] = harness.strat.checkBalance() + + initial_deposit = harness.pool_create_mix(tilt=0.5, size=1.5) + harness.vault_admin.depositToStrategy(harness.strat, list(initial_deposit.keys()), list(initial_deposit.values()), {'from':STRATEGIST}) + + stat['pre_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['pre_pool_0'] = pb[0] + stat['pre_pool_1'] = pb[1] + + harness.tilt_pool(initial_tilt) + + stat['before_vault'] = harness.vault_core.totalValue() + stat['before_value_in_vault'] = harness.vault_core.totalValueInVault() + stat['before_strat_check_balance'] = harness.strat.checkBalance() + pb = list(harness.pool_balances().values()) + stat['before_pool_0'] = pb[0] + stat['before_pool_1'] = pb[1] + + deposit = harness.pool_create_mix(deposit_mix, size=1) + harness.vault_admin.depositToStrategy(harness.strat, list(deposit.keys()), list(deposit.values()), {'from':STRATEGIST}) + + stat['after_vault'] = harness.vault_core.totalValue() + stat['after_strat_check_balance'] = harness.strat.checkBalance() + stat['after_value_in_vault'] = harness.vault_core.totalValueInVault() + pb = list(harness.pool_balances().values()) + stat['after_pool_0'] = pb[0] + stat['after_pool_1'] = pb[1] + + # after after + harness.vault_admin.withdrawAllFromStrategy(harness.strat, {'from':STRATEGIST}) + + stat['end_vault'] = harness.vault_core.totalValue() + stat['end_strat_check_balance'] = harness.strat.checkBalance() + stat['end_value_in_vault'] = harness.vault_core.totalValueInVault() + + + # profit = stat['after_vault'] - stat['before_vault'] + # end_profit = stat['end_vault'] - stat['start_vault'] + # if (profit > 0): + # profit_strat = stat['after_strat_check_balance'] - stat['before_strat_check_balance'] + # profit_strat += stat['after_value_in_vault'] - stat['before_value_in_vault'] + + # end_value_in_vault_profit = stat['end_value_in_vault'] - stat['start_value_in_vault'] + + # print("PROFITING at MIX ", deposit_mix, deposit) + # print("Vault profit ", profit / 1e18) + # print("Strategy checkBalance() profit ", profit_strat / 1e18) + # print("End vault profit ", end_profit / 1e18) + # print("Value in vault diff ", end_value_in_vault_profit / 1e18) + # print("before_pool_0", stat['before_pool_0'] / 1e18) + # print("before_pool_1", stat['before_pool_1'] / 1e18) + + # total_in_pool = harness.from_reth_to_units(stat['before_pool_0']) + stat['before_pool_1'] + # print("reth_share", harness.from_reth_to_units(stat['before_pool_0']) / total_in_pool) + # print("weth_share", stat['before_pool_1'] / total_in_pool) + + deposit_stats.append(stat) + +pd.DataFrame.from_records(deposit_stats).to_csv("deposit_stats.csv") + + +# Test Balances + +balance_stats = [] +steps = 5 if do_it_fast else 20 +for initial_tilt in [0.0, -1, -3, 1, 3]: + for deposit_x in range (0, steps + 1, 1): + with TemporaryFork(): + stat = {} + + test_tilt = deposit_x / (steps / 2) - 1 + + stat['action'] = 'balance' + stat['action_mix'] = test_tilt + + initial_deposit = harness.pool_create_mix(tilt=0.5, size=1.5) + harness.vault_admin.depositToStrategy(harness.strat, list(initial_deposit.keys()), list(initial_deposit.values()), {'from':STRATEGIST}) + + stat['pre_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['pre_pool_0'] = pb[0] + stat['pre_pool_1'] = pb[1] + + harness.tilt_pool(initial_tilt) + + + stat['before_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['before_pool_0'] = pb[0] + stat['before_pool_1'] = pb[1] + + + harness.tilt_pool(initial_tilt) + + stat['after_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['after_pool_0'] = pb[0] + stat['after_pool_1'] = pb[1] + + balance_stats.append(stat) + +pd.DataFrame.from_records(balance_stats).to_csv("balance_stats.csv") + + +# Test Withdraws + +withdraw_stats = [] +steps = 5 if do_it_fast else 20 +for initial_tilt in [0.0, -1, -3, 1, 3]: + for deposit_x in range (0, steps + 1, 1): + with TemporaryFork(): + stat = {} + + deposit_mix = deposit_x / steps + + stat['action'] = 'withdraw' + stat['action_mix'] = deposit_mix + + initial_deposit = harness.pool_create_mix(tilt=0.5, size=1) + harness.vault_admin.depositToStrategy(harness.strat, list(initial_deposit.keys()), list(initial_deposit.values()), {'from':STRATEGIST}) + + stat['pre_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['pre_pool_0'] = pb[0] + stat['pre_pool_1'] = pb[1] + + harness.tilt_pool(initial_tilt) + + stat['before_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['before_pool_0'] = pb[0] + stat['before_pool_1'] = pb[1] + + withdraw = harness.pool_create_mix(deposit_mix, size=0.4) + try: + harness.vault_admin.withdrawFromStrategy(harness.strat, list(withdraw.keys()), list(withdraw.values()), {'from':STRATEGIST}) + except: + print("WITHDRAWAL FAILED") + + stat['after_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['after_pool_0'] = pb[0] + stat['after_pool_1'] = pb[1] + + withdraw_stats.append(stat) + +pd.DataFrame.from_records(withdraw_stats).to_csv("withdraw_stats.csv") + + +# Test WithdrawAll + +withdrawall_stats = [] +steps = 5 if do_it_fast else 100 +for initial_tilt in range (0, steps + 1, 1): + with TemporaryFork(): + stat = {} + + initial_tilt = (initial_tilt / steps - 0.5) * 4 + + stat['action'] = 'withdrawall' + stat['action_mix'] = initial_tilt + + initial_deposit = harness.pool_create_mix(tilt=0.5, size=1.5) + harness.vault_admin.depositToStrategy(harness.strat, list(initial_deposit.keys()), list(initial_deposit.values()), {'from':STRATEGIST}) + + stat['pre_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['pre_pool_0'] = pb[0] + stat['pre_pool_1'] = pb[1] + + harness.tilt_pool(initial_tilt) + + stat['before_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['before_pool_0'] = pb[0] + stat['before_pool_1'] = pb[1] + + harness.vault_admin.withdrawAllFromStrategy(harness.strat, {'from':STRATEGIST}) + + stat['after_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['after_pool_0'] = pb[0] + stat['after_pool_1'] = pb[1] + + withdrawall_stats.append(stat) + +pd.DataFrame.from_records(withdrawall_stats).to_csv("withdrawall_stats.csv") \ No newline at end of file diff --git a/brownie/balancer_test/withdraw_stats.csv b/brownie/balancer_test/withdraw_stats.csv new file mode 100644 index 0000000000..a455a2e4a5 --- /dev/null +++ b/brownie/balancer_test/withdraw_stats.csv @@ -0,0 +1,31 @@ +,action,action_mix,pre_vault,pre_pool_0,pre_pool_1,before_vault,before_pool_0,before_pool_1,after_vault,after_pool_0,after_pool_1 +0,withdraw,0.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712285990899617689803,14042934255027827229176,15857742858560606821195 +1,withdraw,0.2,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712318679268686733821,14082934255027827229176,15817742858560606821193 +2,withdraw,0.4,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712346928569983895535,14122934255027827229176,15777742858560606821193 +3,withdraw,0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712370742699490743493,14162934255027827229176,15737742858560606821193 +4,withdraw,0.8,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712390125180310793019,14202934255027827229176,15697742858560606821193 +5,withdraw,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712405079163675883675,14242934255027827229177,15657742858560606821193 +6,withdraw,0.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712907239753383757931,16042534255027827228867,13696838662245246369677 +7,withdraw,0.2,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712705156079163936705,16082534255027827228867,13656838662245246369675 +8,withdraw,0.4,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712498312451758763863,16122534255027827228867,13616838662245246369675 +9,withdraw,0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712286692768839241095,16162534255027827228867,13576838662245246369675 +10,withdraw,0.8,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66712070280495850937741,16202534255027827228867,13536838662245246369675 +11,withdraw,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712486070847604102015,16242934255027827229177,13696838662245246369677,66711849058662693978309,16242534255027827228868,13496838662245246369675 +12,withdraw,0.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66714317793272674177193,20041734255027827228817,9418524985019827218314 +13,withdraw,0.2,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66713419368734843081303,20081734255027827228817,9378524985019827218312 +14,withdraw,0.4,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66712510721956842114829,20121734255027827228817,9338524985019827218312 +15,withdraw,0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66711591739161928730677,20161734255027827228817,9298524985019827218312 +16,withdraw,0.8,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66710662304538063440423,20201734255027827228817,9258524985019827218312 +17,withdraw,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712657203301000321325,20242934255027827229177,9418524985019827218314,66709722300195961736931,20241734255027827228818,9218524985019827218312 +18,withdraw,0.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66711703715544010222845,12203127351718788647367,17857342858560606820771 +19,withdraw,0.2,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66711959615738691865927,12243127351718788647367,17817342858560606820769 +20,withdraw,0.4,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712210450656654198719,12283127351718788647367,17777342858560606820769 +21,withdraw,0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712456244533635388233,12323127351718788647367,17737342858560606820769 +22,withdraw,0.8,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712697021084502758137,12363127351718788647367,17697342858560606820769 +23,withdraw,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712479407520681295659,12403127351718788647368,17857742858560606821195,66712932803509124599594,12403127351718788647368,17657342858560606820769 +24,withdraw,0.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66709538425777371864729,8558359650672231433064,21856542858560606821465 +25,withdraw,0.2,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66710481913174103361223,8598359650672231433064,21816542858560606821463 +26,withdraw,0.4,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66711414275841675431583,8638359650672231433064,21776542858560606821463 +27,withdraw,0.6,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66712335647775029067205,8678359650672231433064,21736542858560606821463 +28,withdraw,0.8,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66713246160454773312660,8718359650672231433064,21696542858560606821463 +29,withdraw,1.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712637440111575935083,8758359650672231433065,21857742858560606821195,66714145942902247349671,8758359650672231433065,21656542858560606821463 diff --git a/brownie/balancer_test/withdrawall_stats.csv b/brownie/balancer_test/withdrawall_stats.csv new file mode 100644 index 0000000000..75176989c6 --- /dev/null +++ b/brownie/balancer_test/withdrawall_stats.csv @@ -0,0 +1,7 @@ +,action,action_mix,pre_vault,pre_pool_0,pre_pool_1,before_vault,before_pool_0,before_pool_1,after_vault,after_pool_0,after_pool_1 +0,withdrawall,-2.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712571953913925670961,18242934255027827229177,11548950629685360095223,66714746010881574661102,16420102681620710042601,10395436879987620336804 +1,withdrawall,-1.2,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712503287545946214832,16642934255027827229177,13266136421070725397652,66713177442335945992926,14980199351751540141657,11941109476394284935556 +2,withdrawall,-0.3999999999999999,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712434312317354167843,15042934255027826929177,14991946602558435487759,66712470281279603861620,13540296021882369970943,13494545055414007752686 +3,withdrawall,0.3999999999999999,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712431638950270851343,13505867050482667428761,16657742858560606521195,66712544799494050718437,12156895715868359306935,14993816904389017256114 +4,withdrawall,1.2000000000000002,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712495299215122511647,12036352111368635374694,18257742858560607321195,66713323271743301974538,10834156509200284929828,16433720234258187876648 +5,withdrawall,2.0,66712399716827024805155,14242934255027827229177,15857742858560606821195,66712558692923073741931,10573783010213309875302,19857742858560606821195,66714853267974253915139,9517669387452615412383,17873623564127357327924 diff --git a/brownie/scripts/strategy_harness.py b/brownie/scripts/strategy_harness.py new file mode 100644 index 0000000000..ed22f65c87 --- /dev/null +++ b/brownie/scripts/strategy_harness.py @@ -0,0 +1,307 @@ +# Tilt Tester +from world import * +from brownie import chain +import random +import pandas as pd + +WSTETH_WHALE = "0x176f3dab24a159341c0509bb36b833e7fdd0a132" +WETH_WHALE = "0x8EB8a3b98659Cce290402893d0123abb75E3ab28" +WETH_WHALE2 = "0xf04a5cc80b1e94c69b48f5ee68a08cd2f09a7c3e" +RETH_WHALE = "0xCc9EE9483f662091a1de4795249E24aC0aC2630f" +RETH_WHALE2 = "0xC6424e862f1462281B0a5FAc078e4b63006bDEBF" +strat_address = "0x85094b52754591A3dE0002AD97F433584389aea0" + +do_it_fast = False + +class BalancerRethEth: + def __init__(self): + pool_address = "0x1E19CF2D73a72Ef1332C882F20534B6519Be0276" + self.strat = load_contract("balancer_strat", strat_address) + self.pool = load_contract("balancer_metastablepool", pool_address) + self.name = "Balancer Steth-Eth Metastable" + self.vault_core = oeth_vault_core + self.vault_admin = oeth_vault_admin + self.base_size = 2000 + + self.strat.setMaxDepositDeviation(1e18, {'from': STRATEGIST}) # == 100% + self.strat.setMaxWithdrawalDeviation(4 * 1e18, {'from': STRATEGIST}) # == 100% + self._balancer_vault = load_contract("balancer_vault", self.pool.getVault()) + self._pool_pid = "0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112" + self._pool_tokens = self.pool_balances().keys() + self.rethExchangeRate = reth.getExchangeRate() + + reth.approve(self._balancer_vault, 1e70, {'from': RETH_WHALE}) + weth.approve(self._balancer_vault, 1e70, {'from': WETH_WHALE}) + + def pool_balances(self): + balances = self._balancer_vault.getPoolTokens(self._pool_pid)[0:2] + return dict(zip(balances[0], balances[1])) + + def to_reth_amount(self, amount): + return amount * 1e18 / self.rethExchangeRate + + def from_reth_to_units(self, amount): + return amount * self.rethExchangeRate / 1e18 + + # put the pool to exact 50%/50% share + def balance_pool(self): + (reth_balance, weth_balance) = list(harness.pool_balances().values()) + reth_unit_balance = self.from_reth_to_units(reth_balance) + + if reth_unit_balance > weth_balance: + # convert from unit amount to reth amoount + weth_amount = (reth_unit_balance - weth_balance) / 2 + # swapping WETH specified by amount for RETH + self._balancer_vault.swap((self._pool_pid, 0, WETH, RETH, weth_amount, ""), (WETH_WHALE, False, WETH_WHALE, False), 1, chain.time()+100, {"from": WETH_WHALE}) + else: + to_reth_amount = self.to_reth_amount(weth_balance - reth_unit_balance) / 2 + # swapping RETH specified by amount for WETH + self._balancer_vault.swap((self._pool_pid, 0, RETH, WETH, to_reth_amount, ""), (RETH_WHALE, False, RETH_WHALE, False), 1, chain.time()+100, {"from": RETH_WHALE}) + + def tilt_pool(self, size): + self.balance_pool() + amount = abs(size) * self.base_size * int(1e18) + if size == 0: + pass + elif size > 0: + # swapping WETH specified by amount for RETH + self._balancer_vault.swap((self._pool_pid, 0, WETH, RETH, amount, ""), (WETH_WHALE, False, WETH_WHALE, False), 1, chain.time()+100, {"from": WETH_WHALE}) + else: + # swapping RETH specified by amount for WETH + self._balancer_vault.swap((self._pool_pid, 0, RETH, WETH, amount, ""), (RETH_WHALE, False, RETH_WHALE, False), 1, chain.time()+100, {"from": RETH_WHALE}) + + def pool_create_mix(self, tilt=0.5, size=1): + return { + # account for rethExchangeRate + RETH: self.to_reth_amount(int(size * self.base_size * (int(1e18)-(int(1e18) * tilt)))), + WETH: int(size * self.base_size * int(1e18) * tilt), + } + +harness = BalancerRethEth() + +# Run setup +try: + harness.vault_admin.withdrawAllFromStrategies({'from':STRATEGIST}) +except: + print("Withdraw all failed") + +harness.vault_admin.withdrawAllFromStrategy(harness.strat, {'from':STRATEGIST}) +if (weth.balanceOf(harness.vault_admin) < 2e4 * int(1e18)): + weth.transfer(harness.vault_admin, 2e4 * int(1e18), {'from': WETH_WHALE2}) +if (reth.balanceOf(harness.vault_admin) < 2e4 * int(1e18)): + reth.transfer(harness.vault_admin, 2e4 * int(1e18), {'from': RETH_WHALE2}) + +# Test Deposits + +deposit_stats = [] +steps = 20 if do_it_fast else 60 +for initial_tilt in [0.0, -1, -3, 1, 3]: +#for initial_tilt in [0.0]: + for deposit_x in range (0, steps + 1, 1): + #for deposit_mix in [0.4, 0.45]: + with TemporaryFork(): + stat = {} + + deposit_mix = deposit_x / steps + + stat['action'] = 'deposit' + stat['action_mix'] = deposit_mix + + stat['start_vault'] = harness.vault_core.totalValue() + stat['start_value_in_vault'] = harness.vault_core.totalValueInVault() + stat['start_strat_check_balance'] = harness.strat.checkBalance() + + initial_deposit = harness.pool_create_mix(tilt=0.5, size=1.5) + harness.vault_admin.depositToStrategy(harness.strat, list(initial_deposit.keys()), list(initial_deposit.values()), {'from':STRATEGIST}) + + stat['pre_vault'] = harness.vault_core.totalValue() + pb = list(harness.pool_balances().values()) + stat['pre_pool_0'] = pb[0] + stat['pre_pool_1'] = pb[1] + + harness.tilt_pool(initial_tilt) + + stat['before_vault'] = harness.vault_core.totalValue() + stat['before_value_in_vault'] = harness.vault_core.totalValueInVault() + stat['before_strat_check_balance'] = harness.strat.checkBalance() + pb = list(harness.pool_balances().values()) + stat['before_pool_0'] = pb[0] + stat['before_pool_1'] = pb[1] + + deposit = harness.pool_create_mix(deposit_mix, size=1) + harness.vault_admin.depositToStrategy(harness.strat, list(deposit.keys()), list(deposit.values()), {'from':STRATEGIST}) + + stat['after_vault'] = harness.vault_core.totalValue() + stat['after_strat_check_balance'] = harness.strat.checkBalance() + stat['after_value_in_vault'] = harness.vault_core.totalValueInVault() + pb = list(harness.pool_balances().values()) + stat['after_pool_0'] = pb[0] + stat['after_pool_1'] = pb[1] + + # after after + harness.vault_admin.withdrawAllFromStrategy(harness.strat, {'from':STRATEGIST}) + + stat['end_vault'] = harness.vault_core.totalValue() + stat['end_strat_check_balance'] = harness.strat.checkBalance() + stat['end_value_in_vault'] = harness.vault_core.totalValueInVault() + + + # profit = stat['after_vault'] - stat['before_vault'] + # end_profit = stat['end_vault'] - stat['start_vault'] + # if (profit > 0): + # profit_strat = stat['after_strat_check_balance'] - stat['before_strat_check_balance'] + # profit_strat += stat['after_value_in_vault'] - stat['before_value_in_vault'] + + # end_value_in_vault_profit = stat['end_value_in_vault'] - stat['start_value_in_vault'] + + # print("PROFITING at MIX ", deposit_mix, deposit) + # print("Vault profit ", profit / 1e18) + # print("Strategy checkBalance() profit ", profit_strat / 1e18) + # print("End vault profit ", end_profit / 1e18) + # print("Value in vault diff ", end_value_in_vault_profit / 1e18) + # print("before_pool_0", stat['before_pool_0'] / 1e18) + # print("before_pool_1", stat['before_pool_1'] / 1e18) + + # total_in_pool = harness.from_reth_to_units(stat['before_pool_0']) + stat['before_pool_1'] + # print("reth_share", harness.from_reth_to_units(stat['before_pool_0']) / total_in_pool) + # print("weth_share", stat['before_pool_1'] / total_in_pool) + + deposit_stats.append(stat) + +pd.DataFrame.from_records(deposit_stats).to_csv("deposit_stats.csv") + + +# # Test Balances + +# balance_stats = [] +# steps = 5 if do_it_fast else 20 +# for initial_tilt in [0.0, -1, -3, 1, 3]: +# for deposit_x in range (0, steps + 1, 1): +# with TemporaryFork(): +# stat = {} + +# test_tilt = deposit_x / (steps / 2) - 1 + +# stat['action'] = 'balance' +# stat['action_mix'] = test_tilt + +# initial_deposit = harness.pool_create_mix(tilt=0.5, size=1.5) +# harness.vault_admin.depositToStrategy(harness.strat, list(initial_deposit.keys()), list(initial_deposit.values()), {'from':STRATEGIST}) + +# stat['pre_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['pre_pool_0'] = pb[0] +# stat['pre_pool_1'] = pb[1] + +# harness.tilt_pool(initial_tilt) + + +# stat['before_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['before_pool_0'] = pb[0] +# stat['before_pool_1'] = pb[1] + + +# harness.tilt_pool(initial_tilt) + +# stat['after_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['after_pool_0'] = pb[0] +# stat['after_pool_1'] = pb[1] + +# balance_stats.append(stat) + +# pd.DataFrame.from_records(balance_stats).to_csv("balance_stats.csv") + + +# Test Withdraws + +# withdraw_stats = [] +# steps = 5 if do_it_fast else 20 +# for initial_tilt in [0.0, -1, -3, 1, 3]: +# #for initial_tilt in [0.0]: +# for deposit_x in range (0, steps + 1, 1): +# with TemporaryFork(): +# stat = {} + +# deposit_mix = deposit_x / steps + +# stat['action'] = 'withdraw' +# stat['action_mix'] = deposit_mix + +# initial_deposit = harness.pool_create_mix(tilt=0.5, size=1.5) +# #initial_deposit = harness.pool_create_mix(tilt=0.5, size=1) +# print("XX0", initial_deposit) +# harness.vault_admin.depositToStrategy(harness.strat, list(initial_deposit.keys()), list(initial_deposit.values()), {'from':STRATEGIST}) + +# print("XX1") +# stat['pre_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['pre_pool_0'] = pb[0] +# stat['pre_pool_1'] = pb[1] + +# harness.tilt_pool(initial_tilt) + +# stat['before_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['before_pool_0'] = pb[0] +# stat['before_pool_1'] = pb[1] + +# withdraw = harness.pool_create_mix(deposit_mix, size=0.1) +# #withdraw = harness.pool_create_mix(deposit_mix, size=0.4) +# print("XX2", withdraw) +# try: +# harness.vault_admin.withdrawFromStrategy(harness.strat, list(withdraw.keys()), list(withdraw.values()), {'from':STRATEGIST}) +# except: +# print("WITHDRAWAL FAILED") + +# print("XX3") +# stat['after_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['after_pool_0'] = pb[0] +# stat['after_pool_1'] = pb[1] + +# withdraw_stats.append(stat) + +# pd.DataFrame.from_records(withdraw_stats).to_csv("withdraw_stats.csv") + + +# # Test WithdrawAll + +# withdrawall_stats = [] +# steps = 5 if do_it_fast else 100 +# for initial_tilt in range (0, steps + 1, 1): +# with TemporaryFork(): +# stat = {} + +# initial_tilt = (initial_tilt / steps - 0.5) * 4 + +# stat['action'] = 'withdrawall' +# stat['action_mix'] = initial_tilt + +# initial_deposit = harness.pool_create_mix(tilt=0.5, size=1.5) +# harness.vault_admin.depositToStrategy(harness.strat, list(initial_deposit.keys()), list(initial_deposit.values()), {'from':STRATEGIST}) + +# stat['pre_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['pre_pool_0'] = pb[0] +# stat['pre_pool_1'] = pb[1] + +# harness.tilt_pool(initial_tilt) + + +# stat['before_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['before_pool_0'] = pb[0] +# stat['before_pool_1'] = pb[1] + +# harness.vault_admin.withdrawAllFromStrategy(harness.strat, {'from':STRATEGIST}) + +# stat['after_vault'] = harness.vault_core.totalValue() +# pb = list(harness.pool_balances().values()) +# stat['after_pool_0'] = pb[0] +# stat['after_pool_1'] = pb[1] + +# withdrawall_stats.append(stat) + +# pd.DataFrame.from_records(withdrawall_stats).to_csv("withdrawall_stats.csv") \ No newline at end of file diff --git a/brownie/world.py b/brownie/world.py index 60065232f0..fb751a899f 100644 --- a/brownie/world.py +++ b/brownie/world.py @@ -40,7 +40,7 @@ def load_contract(name, address): wsteth = load_contract('wsteth', WSTETH) sfrxeth = load_contract('ERC20', SFRXETH) frxeth = load_contract('ERC20', FRXETH) -reth = load_contract('ERC20', RETH) +reth = load_contract('reth', RETH) flipper = load_contract('flipper', FLIPPER) #buyback = load_contract('buyback', BUYBACK) @@ -84,7 +84,6 @@ def load_contract(name, address): oeth = load_contract('ERC20', OETH) weth = load_contract('ERC20', WETH) -reth = load_contract('ERC20', RETH) steth = load_contract('ERC20', STETH) frxeth = load_contract('ERC20', FRXETH) sfrxeth = load_contract('ERC20', SFRXETH) diff --git a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol index b45241cbfc..451e1fda62 100644 --- a/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol +++ b/contracts/contracts/strategies/balancer/BalancerMetaPoolStrategy.sol @@ -12,6 +12,7 @@ import { IRateProvider } from "../../interfaces/balancer/IRateProvider.sol"; import { IMetaStablePool } from "../../interfaces/balancer/IMetaStablePool.sol"; import { IERC20, InitializableAbstractStrategy } from "../../utils/InitializableAbstractStrategy.sol"; import { StableMath } from "../../utils/StableMath.sol"; +import "hardhat/console.sol"; contract BalancerMetaPoolStrategy is BaseAuraStrategy { using SafeERC20 for IERC20; @@ -154,7 +155,7 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { bytes memory userData = abi.encode( IBalancerVault.WeightedPoolJoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, amountsIn, - minBPTwDeviation + 0 ); IBalancerVault.JoinPoolRequest memory request = IBalancerVault @@ -222,6 +223,11 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { address[] memory _strategyAssets, uint256[] memory _strategyAmounts ) internal { + if (_strategyAmounts.length == 1 && _strategyAmounts[0] == 0) { + // nothing to do + return; + } + require( _strategyAssets.length == _strategyAmounts.length, "Invalid input arrays" @@ -258,6 +264,10 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { // for each of the vault assets for (uint256 j = 0; j < _strategyAssets.length; ++j) { + if (_strategyAmounts[j] == 0) { + continue; + } + // If the vault asset equals the vault asset mapped from the Balancer pool asset if (_strategyAssets[j] == strategyAsset) { (, poolAssetsAmountsOut[i]) = _toPoolAsset( @@ -316,6 +326,10 @@ contract BalancerMetaPoolStrategy is BaseAuraStrategy { * ['uint256', 'uint256[]', 'uint256'] * [BPT_IN_FOR_EXACT_TOKENS_OUT, amountsOut, maxBPTAmountIn] */ + console.log("BPT TO WITHDRAW"); + console.log(maxBPTtoWithdraw); + console.log(_strategyAmounts[0]); + bytes memory userData = abi.encode( IBalancerVault.WeightedPoolExitKind.BPT_IN_FOR_EXACT_TOKENS_OUT, poolAssetsAmountsOut, diff --git a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol index f046c2fb82..09153715eb 100644 --- a/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol +++ b/contracts/contracts/strategies/balancer/BaseBalancerStrategy.sol @@ -441,10 +441,7 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { external onlyVaultOrGovernorOrStrategist { - require( - _maxWithdrawalDeviation <= 1e18, - "Withdrawal dev. out of bounds" - ); + emit MaxWithdrawalDeviationUpdated( maxWithdrawalDeviation, _maxWithdrawalDeviation @@ -466,7 +463,6 @@ abstract contract BaseBalancerStrategy is InitializableAbstractStrategy { external onlyVaultOrGovernorOrStrategist { - require(_maxDepositDeviation <= 1e18, "Deposit dev. out of bounds"); emit MaxDepositDeviationUpdated( maxDepositDeviation, _maxDepositDeviation diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index efa8f2ca41..2c3ac06236 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -395,6 +395,10 @@ contract VaultCore is VaultInitializer { return _totalValueInVault() + _totalValueInStrategies(); } + function totalValueInVault() external view virtual returns (uint256 value) { + return _totalValueInVault(); + } + /** * @dev Internal to calculate total value of all assets held in Vault. * @return value Total value in ETH (1e18) diff --git a/contracts/deploy/066_oeth_vault_swaps.js b/contracts/deploy/066_oeth_vault_swaps.js index f8ce4f7a79..d4e32ccab0 100644 --- a/contracts/deploy/066_oeth_vault_swaps.js +++ b/contracts/deploy/066_oeth_vault_swaps.js @@ -1,11 +1,11 @@ -const { deploymentWithProposal } = require("../utils/deploy"); +const { deploymentWithGovernanceProposal } = require("../utils/deploy"); -module.exports = deploymentWithProposal( +module.exports = deploymentWithGovernanceProposal( { deployName: "066_oeth_vault_swaps", forceDeploy: false, reduceQueueTime: true, - proposalId: 54, + //proposalId: 54, }, async ({ assetAddresses, deployWithConfirmation }) => { // Deployer Actions diff --git a/contracts/deployments/mainnet/.migrations.json b/contracts/deployments/mainnet/.migrations.json index 83765c0d9c..b300557b4f 100644 --- a/contracts/deployments/mainnet/.migrations.json +++ b/contracts/deployments/mainnet/.migrations.json @@ -61,7 +61,6 @@ "064_oeth_morpho_aave_v2": 1685393284, "065_oeth_swapper": 1685701143, "065_upgrade_fraxeth_strategy": 1687175786, - "066_oeth_vault_swaps": 1687744974, "067_ousd_vault_value_checker": 1687280260, "068_oeth_to_ogv_governance_p1": 1687795046, "069_oeth_to_ogv_governance_p2": 1687955800, From 73a26e0b719c8295fbd784b233677a74c54c9584 Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 1 Feb 2024 08:19:36 +0100 Subject: [PATCH 67/67] intermediary work --- .../jupyter/OETHVaultCoreExposed.sol | 17 ++++ .../contracts/jupyter/VaultCoreExposed.sol | 17 ++++ contracts/contracts/vault/VaultCore.sol | 4 - contracts/dev.env | 6 +- contracts/node.sh | 4 + contracts/tasks/hotDeploy.js | 16 +++ contracts/tasks/tasks.js | 2 + contracts/test/_fixture.js | 99 ------------------- contracts/test/_hot-deploy.js | 25 ++++- contracts/test/helpers.js | 3 +- 10 files changed, 83 insertions(+), 110 deletions(-) create mode 100644 contracts/contracts/jupyter/OETHVaultCoreExposed.sol create mode 100644 contracts/contracts/jupyter/VaultCoreExposed.sol create mode 100644 contracts/tasks/hotDeploy.js diff --git a/contracts/contracts/jupyter/OETHVaultCoreExposed.sol b/contracts/contracts/jupyter/OETHVaultCoreExposed.sol new file mode 100644 index 0000000000..7bb1ec193a --- /dev/null +++ b/contracts/contracts/jupyter/OETHVaultCoreExposed.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title OETHVaultCoreExposed contract + * @notice Contract that exposes additional data points required by the Jupyter + * research notebook + * @author Origin Protocol Inc + */ + +import { OETHVaultCore } from "../vault/OETHVaultCore.sol"; + +contract OETHVaultCoreExposed is OETHVaultCore { + function totalValueInVault() external view virtual returns (uint256 value) { + return _totalValueInVault(); + } +} diff --git a/contracts/contracts/jupyter/VaultCoreExposed.sol b/contracts/contracts/jupyter/VaultCoreExposed.sol new file mode 100644 index 0000000000..87b2507548 --- /dev/null +++ b/contracts/contracts/jupyter/VaultCoreExposed.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title VaultCoreExposed contract + * @notice Contract that exposes additional data points required by the Jupyter + * research notebook + * @author Origin Protocol Inc + */ + +import { VaultCore } from "../vault/VaultCore.sol"; + +contract VaultCoreExposed is VaultCore { + function totalValueInVault() external view virtual returns (uint256 value) { + return _totalValueInVault(); + } +} diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index 95aef3e6d8..3eea4968fd 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -395,10 +395,6 @@ contract VaultCore is VaultInitializer { return _totalValueInVault() + _totalValueInStrategies(); } - function totalValueInVault() external view virtual returns (uint256 value) { - return _totalValueInVault(); - } - /** * @dev Internal to calculate total value of all assets held in Vault. * @return value Total value in USD/ETH (1e18) diff --git a/contracts/dev.env b/contracts/dev.env index 8b38880f76..448380da61 100644 --- a/contracts/dev.env +++ b/contracts/dev.env @@ -25,5 +25,9 @@ ACCOUNTS_TO_FUND= # Specify which contracts you want to have their source code hot deployed - swapped without the # need of running migration scripts. - # HOT_DEPLOY=strategy,vaultCore,vaultAdmin,harvester + +# Set to true if you want the node to be setup with additional exposed functionality required +# by the Jupyter +# JUPYTER_FIXTURE=false + diff --git a/contracts/node.sh b/contracts/node.sh index 1851fc601e..b8eaa51537 100755 --- a/contracts/node.sh +++ b/contracts/node.sh @@ -57,6 +57,10 @@ main() FORK=true npx hardhat fund --amount 100000 --network localhost --accountsfromenv true & + if [[ "$JUPYTER_FIXTURE" == "true" ]]; then + FORK=true npx hardhat jupyterFixture --network localhost & + fi + # wait for subprocesses to finish for job in `jobs -p` do diff --git a/contracts/tasks/hotDeploy.js b/contracts/tasks/hotDeploy.js new file mode 100644 index 0000000000..1ffc149f4c --- /dev/null +++ b/contracts/tasks/hotDeploy.js @@ -0,0 +1,16 @@ +const log = require("../utils/logger")("task:hot-deploy"); +const { hotDeployVaultAdmin } = require("../test/_hot-deploy") + +async function jupyterFixture(taskArguments, hre) { + await hotDeployVaultAdmin( + {}, // fixture + false, // deployVaultAdmin + true, // deployVaultCore + true, // isOeth + true // isJupiterDeploy + ); +} + +module.exports = { + jupyterFixture +}; diff --git a/contracts/tasks/tasks.js b/contracts/tasks/tasks.js index e013cbd41b..dac2cd3d0d 100644 --- a/contracts/tasks/tasks.js +++ b/contracts/tasks/tasks.js @@ -3,6 +3,7 @@ const { subtask, task, types } = require("hardhat/config"); const { fund } = require("./account"); const { debug } = require("./debug"); const { env } = require("./env"); +const { jupyterFixture } = require("./hotDeploy"); const { execute, executeOnFork, proposal, governors } = require("./governance"); const { smokeTest, smokeTestCheck } = require("./smokeTest"); const { @@ -70,6 +71,7 @@ task("fund", "Fund accounts on local or fork") // Debug tasks. task("debug", "Print info about contracts and their configs", debug); +task("jupyterFixture", "Run the jupyterFixture that sets up contracts for jupyter notebook data collection", jupyterFixture) // Token tasks. subtask("allowance", "Get the token allowance an owner has given to a spender") diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 829ce398de..5dc39b75fa 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -52,10 +52,7 @@ const threepoolSwapAbi = require("./abi/threepoolSwap.json"); const sfrxETHAbi = require("./abi/sfrxETH.json"); const { defaultAbiCoder, parseUnits, parseEther } = require("ethers/lib/utils"); const balancerStrategyDeployment = require("../utils/balancerStrategyDeployment"); -<<<<<<< HEAD -======= const { impersonateAndFund } = require("../utils/signers"); ->>>>>>> origin/master const log = require("../utils/logger")("test:fixtures"); @@ -268,10 +265,7 @@ const defaultFixture = deployments.createFixture(async () => { fusdt = await ethers.getContractAt(erc20Abi, addresses.mainnet.fUSDT); aura = await ethers.getContractAt(erc20Abi, addresses.mainnet.AURA); bal = await ethers.getContractAt(erc20Abi, addresses.mainnet.BAL); -<<<<<<< HEAD -======= ogv = await ethers.getContractAt(erc20Abi, addresses.mainnet.OGV); ->>>>>>> origin/master crvMinter = await ethers.getContractAt( crvMinterAbi, @@ -336,15 +330,12 @@ const defaultFixture = deployments.createFixture(async () => { balancerREthStrategy = await ethers.getContractAt( "BalancerMetaPoolStrategy", balancerRethStrategyProxy.address -<<<<<<< HEAD ); const oethHarvesterProxy = await ethers.getContract("OETHHarvesterProxy"); oethHarvester = await ethers.getContractAt( "OETHHarvester", oethHarvesterProxy.address -======= ->>>>>>> origin/master ); convexEthMetaStrategyProxy = await ethers.getContract( @@ -363,21 +354,6 @@ const defaultFixture = deployments.createFixture(async () => { oethZapper = await ethers.getContract("OETHZapper"); -<<<<<<< HEAD - // Replace OracleRouter to disable staleness - const dMockOracleRouterNoStale = await deployWithConfirmation( - "MockOracleRouterNoStale" - ); - const dMockOETHOracleRouterNoStale = await deployWithConfirmation( - "MockOETHOracleRouterNoStale" - ); - await replaceContractAt(oracleRouter.address, dMockOracleRouterNoStale); - await replaceContractAt( - oethOracleRouter.address, - dMockOETHOracleRouterNoStale - ); -======= ->>>>>>> origin/master swapper = await ethers.getContract("Swapper1InchV5"); const fluxStrategyProxy = await ethers.getContract("FluxStrategyProxy"); @@ -1731,82 +1707,7 @@ async function nodeRevert(snapshotId) { return await hre.network.provider.request({ method: "evm_revert", params: [snapshotId], -<<<<<<< HEAD - }); -} - -async function _hardhatSetBalance(address, amount = "10000") { - await hre.network.provider.request({ - method: "hardhat_setBalance", - params: [ - address, - parseEther(amount) - .toHexString() - .replace(/^0x0+/, "0x") - .replace(/0$/, "1"), - ], - }); -} - -async function impersonateAndFundContract(address, amount = "100000") { - await impersonateAccount(address); - if (parseFloat(amount) > 0) { - await _hardhatSetBalance(address, amount); - } - - const signer = await ethers.provider.getSigner(address); - signer.address = address; - return signer; -} - -async function impersonateAndFundAddress( - tokenAddress, - contractAddresses, - toAddress, - balanceToUse = 30, // 30% - maxAmount = ethers.BigNumber.from(0) -) { - if (!Array.isArray(contractAddresses)) { - contractAddresses = [contractAddresses]; - } - - let amountTransfered = ethers.BigNumber.from("0"); - for (const contractAddress of contractAddresses) { - const impersonatedSigner = await impersonateAndFundContract( - contractAddress - ); - - const tokenContract = await ethers.getContractAt(daiAbi, tokenAddress); - - const balance = await tokenContract - .connect(impersonatedSigner) - .balanceOf(contractAddress); - - const amount = balance.mul(balanceToUse).div(100); - // consider max amount - if (maxAmount.gt(ethers.BigNumber.from("0"))) { - if (amountTransfered.add(amount).gt(maxAmount)) { - await tokenContract - .connect(impersonatedSigner) - .transfer(toAddress, maxAmount.sub(amountTransfered)); - - // max amount already transferred - return; - } - - amountTransfered.add(amount); - } - - await tokenContract.connect(impersonatedSigner).transfer(toAddress, amount); - } -} - -======= - }); -} - ->>>>>>> origin/master async function resetAllowance( tokenContract, signer, diff --git a/contracts/test/_hot-deploy.js b/contracts/test/_hot-deploy.js index e803d5b71f..0611d1b41b 100644 --- a/contracts/test/_hot-deploy.js +++ b/contracts/test/_hot-deploy.js @@ -2,9 +2,12 @@ * used for fork-contract development process where the standalone (separate terminal) node * doesn't need to be restarted to pick up code and ABI changes. */ -const { ethers } = hre; - -const { isFork, isCI } = require("./helpers"); +const isFork = process.env.FORK === "true"; +const isCI = process.env.GITHUB_ACTIONS; +/* can not import the above functionality from ./helpers since hardhat task jupyterFixture + * imports this file and hardhat isn't available as an import yet when tasks are setup. + */ +//const { isFork, isCI } = require("./helpers"); const addresses = require("../utils/addresses"); const { balancer_rETH_WETH_PID, @@ -92,6 +95,7 @@ async function constructNewContract(fixture, implContractName) { }); log(`Deployed`); + const { ethers } = (await import("hardhat")).default; return await ethers.getContract(implContractName); } @@ -169,14 +173,20 @@ async function hotDeployVaultAdmin( fixture, deployVaultAdmin, deployVaultCore, - isOeth + isOeth, + isJupiterDeploy = false ) { const { deploy } = deployments; const vaultProxyName = `${isOeth ? "OETH" : ""}VaultProxy`; - const vaultCoreName = `${isOeth ? "OETH" : ""}VaultCore`; + let vaultCoreName = `${isOeth ? "OETH" : ""}VaultCore`; + if (isJupiterDeploy) { + vaultCoreName = `${isOeth ? "OETH" : ""}VaultCoreExposed`; + } const vaultAdminName = `${isOeth ? "OETH" : ""}VaultAdmin`; const vaultVariableName = `${isOeth ? "oethVault" : "vault"}`; + const { ethers } = (await import("hardhat")).default; + const cVaultProxy = await ethers.getContract(vaultProxyName); if (deployVaultAdmin) { @@ -204,6 +214,7 @@ async function hotDeployVaultAdmin( } if (deployVaultCore) { log(`Deploying new ${vaultCoreName} implementation`); + // deploy this contract that exposes internal function await deploy(vaultCoreName, { from: addresses.mainnet.Timelock, // doesn't matter which address deploys it @@ -226,6 +237,7 @@ async function hotDeployVaultAdmin( } async function hotDeployHarvester(fixture, forOETH) { + const { ethers } = (await import("hardhat")).default; const { deploy } = deployments; const harvesterName = `${forOETH ? "OETH" : ""}Harvester`; const harvesterProxyName = `${forOETH ? "OETH" : ""}HarvesterProxy`; @@ -249,6 +261,7 @@ async function hotDeployHarvester(fixture, forOETH) { } async function hotDeployOracleRouter(fixture, forOETH) { + const { ethers } = (await import("hardhat")).default; const { deploy } = deployments; const routerName = `${forOETH ? "OETH" : ""}OracleRouter`; @@ -285,6 +298,7 @@ async function hotDeployFixture( fixtureStrategyVarName, implContractName ) { + const { ethers } = (await import("hardhat")).default; /* Because of the way hardhat fixture caching works it is vital that * the fixtures are loaded before the hot-deployment of contracts. If the * contracts are hot-deployed and fixture load happens afterwards the deployed @@ -317,4 +331,5 @@ async function hotDeployFixture( module.exports = { hotDeployOption, + hotDeployVaultAdmin }; diff --git a/contracts/test/helpers.js b/contracts/test/helpers.js index 42002f50ce..d6467cd528 100644 --- a/contracts/test/helpers.js +++ b/contracts/test/helpers.js @@ -251,7 +251,9 @@ async function humanBalance(user, contract) { return parseFloat(balance.div(divisor).toString()).toFixed(2); } +// if any of the below 2 lines are changed, also change it in _hot-deploy.js file const isFork = process.env.FORK === "true"; +const isCI = process.env.GITHUB_ACTIONS; const isLocalhost = !isFork && hre.network.name === "localhost"; const isMainnet = hre.network.name === "mainnet"; const isTest = process.env.IS_TEST === "true"; @@ -259,7 +261,6 @@ const isSmokeTest = process.env.SMOKE_TEST === "true"; const isMainnetOrFork = isMainnet || isFork; const isForkTest = isFork && isTest; const isForkWithLocalNode = isFork && process.env.LOCAL_PROVIDER_URL; -const isCI = process.env.GITHUB_ACTIONS; /// Advances the EVM time by the given number of seconds const advanceTime = async (seconds) => {