From fe49ca20890997a01ed9b976fa14425d928cea03 Mon Sep 17 00:00:00 2001 From: Jaskaran Singh Date: Sat, 8 Feb 2025 16:21:14 +0530 Subject: [PATCH] Deployed on base sepolia --- .../84532/run-1739011371.json | 57 +++++ .../84532/run-latest.json | 42 ++-- script/DeployVaultFactory.s.sol | 1 - src/Arbitrage.sol | 166 +++++++++------ src/LiquidityManager.sol | 198 +++++------------- src/Vault.sol | 179 ++++++++-------- src/VaultFactory.sol | 3 + test/forked-uint/ArbitrageTest.t.sol | 47 +++++ test/forked-uint/LiquidityManagerTest.t.sol | 46 +--- test/forked-uint/VaultTest.t.sol | 15 +- 10 files changed, 389 insertions(+), 365 deletions(-) create mode 100644 broadcast/DeployVaultFactory.s.sol/84532/run-1739011371.json create mode 100644 test/forked-uint/ArbitrageTest.t.sol diff --git a/broadcast/DeployVaultFactory.s.sol/84532/run-1739011371.json b/broadcast/DeployVaultFactory.s.sol/84532/run-1739011371.json new file mode 100644 index 0000000..3929e08 --- /dev/null +++ b/broadcast/DeployVaultFactory.s.sol/84532/run-1739011371.json @@ -0,0 +1,57 @@ +{ + "transactions": [ + { + "hash": "0x4f6a853d43237dcb7715e1e2e4a5dbf8c6483c200ea9d79eeacd6c3d54802ef4", + "transactionType": "CREATE", + "contractName": "VaultFactory", + "contractAddress": "0x210088ae6ee018133791f20406bb239f1ea98379", + "function": null, + "arguments": null, + "transaction": { + "from": "0x12b2434a1022d5787bf06056f2885fe35de62bf8", + "gas": "0x4b8dbc", + "value": "0x0", + "input": "0x6080604052600c805462ff00ff191662010001179055348015610020575f80fd5b5061015260408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810191909152506040805161012081018252734200000000000000000000000000000000000006815273036cbd53842c5426634e7929541ec2318f3dcf7e602082015273fe45bf4def7223ab1bf83ca17a4462ef1647f7ff9181019190915273571621ce60cebb0c1d442b5afb38b1663c6bf0176060820152734752ba5dbc23f44d87826276bf6fd6b1c372ad2460808201527394cc0aac535ccdb3c01d6787d6413c739ae12bc460a082015273c5290058841028f1614f3a6f0f5816cad0df5e2760c082015273be781d7bdf469f3d94a62cdcc407ace106aeca7460e0820152604d61010082015290565b8051600e80546001600160a01b03199081166001600160a01b03938416179091556020830151600f8054831691841691909117905560408301516010805483169184169190911790556060830151601180548316918416919091179055608083015160128054831691841691909117905560a083015160138054831691841691909117905560c083015160148054831691841691909117905560e083015160158054831691841691909117905561010090920151601680549093169116179055613fc18061021f5f395ff3fe608060405234801561000f575f80fd5b5060043610610090575f3560e01c8063989e6fd911610063578063989e6fd91461018b578063b4bd6f4614610193578063d1a43bda146101a6578063d7b65745146101ae578063f8ccbf471461024c575f80fd5b806347ae49e714610094578063522c441d1461012657806358f674761461012e57806365cacaa41461016e575b5f80fd5b61009c61026f565b60405161011d919081516001600160a01b03908116825260208084015182169083015260408084015182169083015260608084015182169083015260808084015182169083015260a08084015182169083015260c08084015182169083015260e0808401518216908301526101009283015116918101919091526101200190565b60405180910390f35b61009c6102ff565b61015661013c3660046106be565b600d6020525f90815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161011d565b335f908152600d60205260409020546001600160a01b0316610156565b61009c6103a0565b6101566101a13660046106be565b610432565b61009c61051c565b600e54600f546010546011546012546013546014546015546016546101f2986001600160a01b03908116988116978116968116958116948116938116928116911689565b604080516001600160a01b039a8b168152988a1660208a01529689169688019690965293871660608701529186166080860152851660a0850152841660c0840152831660e08301529091166101008201526101200161011d565b600c5461025f9062010000900460ff1681565b604051901515815260200161011d565b610277610666565b5060408051610120810182525f808252735425890298aed601595a70ab815c96711a31bc656020830152739cfcc1b289e59fbe1e769f020c77315df847376092820192909252606081018290526080810182905260a0810182905260c0810191909152738b9b2af4afb389b4a70a474dfd4adcd4a302bb4060e0820152604d61010082015290565b610307610666565b50604080516101208101825273c558dbdd856501fcd9aaf1e62eae57a9f0629a3c81527394a9d9ac8a22534e3faca9f4e7f2e2cf85d5e4c860208201525f91810182905273e3e0106227181958abfba960c13d0fe52c73326560608201526080810182905260a0810182905260c0810191909152736ae43d3271ff6888e7fc43fd7321a503ff73895160e0820152604d61010082015290565b6103a8610666565b6103e66040518060400160405280601881526020017f54657374696e67204f6e20416e76696c204e6574776f726b00000000000000008152506105fd565b5060408051610120810182525f80825260016020830152918101829052606081019190915260026080820152600360a0820152600660c0820152600760e0820152604d61010082015290565b6016546015546011546013546012546040515f95869588956001600160a01b0392831695918316949083169391831692169061046d906106b1565b6001600160a01b0396871681529486166020860152928516604085015290841660608401528316608083015290911660a082015260c001604051809103905ff0801580156104bd573d5f803e3d5ffd5b506001600160a01b038481165f818152600d602052604080822080546001600160a01b031916948616948517905551939450919290917f5d9c31ffa0fecffd7cf379989a3c7af252f0335e0d2a1320b55245912c781f5391a392915050565b610524610666565b5060408051610120810182526006602160991b01815273036cbd53842c5426634e7929541ec2318f3dcf7e602082015273fe45bf4def7223ab1bf83ca17a4462ef1647f7ff9181019190915273571621ce60cebb0c1d442b5afb38b1663c6bf0176060820152734752ba5dbc23f44d87826276bf6fd6b1c372ad2460808201527394cc0aac535ccdb3c01d6787d6413c739ae12bc460a082015273c5290058841028f1614f3a6f0f5816cad0df5e2760c082015273be781d7bdf469f3d94a62cdcc407ace106aeca7460e0820152604d61010082015290565b6106408160405160240161061191906106eb565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b179052610643565b50565b610640815f6a636f6e736f6c652e6c6f6790505f80835160208501845afa505050565b60408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915290565b6138548061073883390190565b5f602082840312156106ce575f80fd5b81356001600160a01b03811681146106e4575f80fd5b9392505050565b5f602080835283518060208501525f5b81811015610717578581018301518582016040015282016106fb565b505f604082860101526040601f19601f830116850101925050509291505056fe60c060405234801562000010575f80fd5b506040516200385438038062003854833981016040819052620000339162000135565b83838383896001600160a01b0381166200006657604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6200007181620000ca565b50600180546001600160a01b039586166001600160a01b0319918216179091556002805494861694821694909417909355908316608052821660a052600380549790921696169590951790945550620001b29350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811462000130575f80fd5b919050565b5f805f805f8060c087890312156200014b575f80fd5b620001568762000119565b9550620001666020880162000119565b9450620001766040880162000119565b9350620001866060880162000119565b9250620001966080880162000119565b9150620001a660a0880162000119565b90509295509295509295565b60805160a051613656620001fe5f395f81816102830152818161048301528181611ffb01526123b301525f8181610244015281816117e301528181611906015261199e01526136565ff3fe608060405234801561000f575f80fd5b5060043610610132575f3560e01c8063a03e4bc3116100b4578063ca11615e11610079578063ca11615e14610327578063dc0661801461033a578063e6e1bdec146103b3578063e8f6daa9146103bb578063f2fde38b146103ce578063f5ff5c76146103e1575f80fd5b8063a03e4bc3146102c8578063a1db9782146102db578063aab76479146102ee578063bcf685ed14610301578063c7d716d714610314575f80fd5b8063715018a6116100fa578063715018a614610237578063735de9f71461023f5780638bdb2afa1461027e5780638da5cb5b146102a557806397feb926146102b5575f80fd5b806321db8240146101365780634a0de08f14610170578063592bac55146101a85780635d631152146101c9578063604e3706146101de575b5f80fd5b61013e6103f4565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0015b60405180910390f35b61018361017e366004612dcc565b61047d565b604080516001600160801b039094168452602084019290925290820152606001610167565b6101bb6101b6366004612e10565b6106c2565b604051908152602001610167565b6101dc6101d7366004612efb565b6107b6565b005b6101f16101ec366004612f51565b610a28565b604051610167919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080918201519181019190915260a00190565b6101dc610ab6565b6102667f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610167565b6102667f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b0316610266565b6101dc6102c3366004612f6c565b610ac9565b600154610266906001600160a01b031681565b6101dc6102e9366004612f6c565b610cb0565b6101bb6102fc366004612efb565b610ebb565b6101dc61030f366004612f51565b6111d5565b6101dc610322366004612fa4565b6111ff565b6101dc61033536600461304c565b61155b565b610381610348366004612f51565b600460208190525f9182526040909120805460018201546002830154600384015493909401546001600160a01b03909216939092909185565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a001610167565b6101bb611720565b600254610266906001600160a01b031681565b6101dc6103dc366004612f51565b61178f565b600354610266906001600160a01b031681565b600154604051632fe4a15f60e21b81523060048201525f91829182918291829182916001600160a01b039091169063bf92857c9060240160c060405180830381865afa158015610446573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061046a91906130b2565b949b939a50919850965094509092509050565b5f805f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828888886040518463ffffffff1660e01b81526004016104d1939291906130f8565b602060405180830381865afa1580156104ec573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105109190613120565b90506001600160a01b0381166105415760405162461bcd60e51b81526004016105389061313b565b60405180910390fd5b5f80876001600160a01b0316896001600160a01b031610610563578789610566565b88885b915091505f80846001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156105a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105cc9190613187565b5050505050915091505f6064826105e39190613228565b90505f6105f1836064613253565b6040516bffffffffffffffffffffffff193060601b16602082015260e884811b603483015282901b60378201529091506001600160a01b0388169063514ea4bf90603a01604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161066991815260200190565b60a060405180830381865afa158015610684573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106a8919061328e565b50929c50909a509850505050505050505093509350939050565b6003545f906001600160a01b03163314806106e657505f546001600160a01b031633145b6107025760405162461bcd60e51b8152600401610538906132e1565b6001600160a01b0385165f9081526004602052604090206001015483111561073c5760405162461bcd60e51b81526004016105389061330e565b61074a8585856001866117cc565b6001600160a01b0386165f9081526004602052604081206001018054929350859290919061077990849061333c565b90915550506001600160a01b0384165f90815260046020526040812060010180548392906107a890849061334f565b909155509095945050505050565b6003546001600160a01b03163314806107d857505f546001600160a01b031633145b6107f45760405162461bcd60e51b8152600401610538906132e1565b6040805180820190915260048152636161766560e01b60209182015283519084012083907fe0a39fef8aa5887c76606e7a14a5db8dc6676191e4866b2a609a3aa003b183291480159061088c575060408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528151908201207f2b05eae252b2d830081b9362c105fc1b4e5f974a0c53bee02c06419c2f4a117e14155b156108ac57806040516303622bc560e21b815260040161053891906133a5565b6001600160a01b0383165f908152600460205260409020600101548211156108e65760405162461bcd60e51b81526004016105389061330e565b6040805180820190915260048152636161766560e01b6020918201528451908501207f1f5c6010755a7783899f9185eb5a247239989e6e1b7994d59f65c55ffc4e7cd70161096d5761093883836119f6565b6001600160a01b0383165f908152600460205260408120600201805484929061096290849061334f565b909155506109f39050565b60408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528451908501207fd4fa151dad4d27cff7e46c9d3efa03e4b1a068b5f3ac411fd3f9be63d0b5ee82016109f3576109c38383611b75565b6001600160a01b0383165f90815260046020526040812060030180548492906109ed90849061334f565b90915550505b6001600160a01b0383165f9081526004602052604081206001018054849290610a1d90849061333c565b909155505050505050565b610a5e6040518060a001604052805f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b506001600160a01b039081165f90815260046020818152604092839020835160a08101855281549095168552600181015491850191909152600281015492840192909252600382015460608401520154608082015290565b610abe611ce0565b610ac75f611d0c565b565b610ad1611ce0565b604051636eb1769f60e11b815233600482015230602482015281906001600160a01b0384169063dd62ed3e90604401602060405180830381865afa158015610b1b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3f91906133b7565b1015610b865760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610538565b6040516323b872dd60e01b8152336004820152306024820152604481018290525f906001600160a01b038416906323b872dd906064016020604051808303815f875af1158015610bd8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bfc91906133ce565b905080610c3d5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610538565b6001600160a01b0383165f9081526004602052604081206001018054849290610c6790849061334f565b90915550506040518281526001600160a01b038416907fab79632de7fe1724598ce2214eaa326d90d48064d2d3397406ecc5769316a5f6906020015b60405180910390a2505050565b610cb8611ce0565b6001600160a01b0382165f90815260046020526040902060010154811115610cf25760405162461bcd60e51b81526004016105389061330e565b816001600160a01b031663095ea7b3610d125f546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af1158015610d5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d8091906133ce565b505f826001600160a01b031663a9059cbb610da25f546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303815f875af1158015610dec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1091906133ce565b905080610e515760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610538565b6001600160a01b0383165f9081526004602052604081206001018054849290610e7b90849061333c565b90915550506040518281526001600160a01b038416907f7e2c99819371db0a6fc6f4269fe872496e44f502df19ba3eae594b7a1598746090602001610ca3565b6003545f906001600160a01b0316331480610edf57505f546001600160a01b031633145b610efb5760405162461bcd60e51b8152600401610538906132e1565b6040805180820190915260048152636161766560e01b60209182015284519085012084907fe0a39fef8aa5887c76606e7a14a5db8dc6676191e4866b2a609a3aa003b1832914801590610f93575060408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528151908201207f2b05eae252b2d830081b9362c105fc1b4e5f974a0c53bee02c06419c2f4a117e14155b15610fb357806040516303622bc560e21b815260040161053891906133a5565b6040805180820190915260048152636161766560e01b6020918201528551908601207f1f5c6010755a7783899f9185eb5a247239989e6e1b7994d59f65c55ffc4e7cd7016110a9576001600160a01b0384165f908152600460205260409020600201548311156110655760405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e7420696e76657374656420616d6f756e74000000006044820152606401610538565b61106f8484611d5b565b6001600160a01b0385165f9081526004602052604081206002018054929450859290919061109e90849061333c565b9091555061119e9050565b60408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528551908601207fd4fa151dad4d27cff7e46c9d3efa03e4b1a068b5f3ac411fd3f9be63d0b5ee820161119e576001600160a01b0384165f9081526004602052604090206003015483111561115f5760405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e7420696e76657374656420616d6f756e74000000006044820152606401610538565b6111698484611e48565b6001600160a01b0385165f9081526004602052604081206003018054929450859290919061119890849061333c565b90915550505b6001600160a01b0384165f90815260046020526040812060010180548492906111c890849061334f565b9091555050509392505050565b6111dd611ce0565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633148061122157505f546001600160a01b031633145b61123d5760405162461bcd60e51b8152600401610538906132e1565b6040805180820190915260078152660756e69737761760cc1b60209182015288519089012088907fa2a03459171c76bff45817330c10ef9f8af07011a33005b73b50189bbc7e7132148015906112d957506040805180820190915260098152686165726f64726f6d6560b81b6020918201528151908201207fc570e6c17f57bc6841b1057f94fcf1785f440006714dbd98f64d859b54cd25d314155b156112f957806040516303622bc560e21b815260040161053891906133a5565b6001600160a01b0388165f908152600460205260409020600101548611156113635760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e742062616c616e636520746f6b656e3000000000006044820152606401610538565b6001600160a01b0387165f908152600460205260409020600101548511156113cd5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e742062616c616e636520746f6b656e3100000000006044820152606401610538565b6040805180820190915260078152660756e69737761760cc1b6020918201528951908a01207f5d5fcba6e8e389400ba7e8ccf3ef1060750f8fee5ccffa48c4afe76443818ece0161148c5761142788888888888888611ff7565b506001600160a01b0388165f908152600460208190526040822001805488929061145290849061334f565b90915550506001600160a01b0387165f908152600460208190526040822001805487929061148190849061334f565b909155506114f29050565b6040805180820190915260098152686165726f64726f6d6560b81b6020918201528951908a01207f3a8f193e80a84397be4efa806b030e87a0bbfff98eb2426709b27a64ab32da2d016114f2576040516305fcd0f760e01b815260040160405180910390fd5b6001600160a01b0388165f908152600460205260408120600101805488929061151c90849061333c565b90915550506001600160a01b0387165f908152600460205260408120600101805487929061154b90849061333c565b9091555050505050505050505050565b6003546001600160a01b031633148061157d57505f546001600160a01b031633145b6115995760405162461bcd60e51b8152600401610538906132e1565b6040805180820190915260078152660756e69737761760cc1b60209182015284519085012084907fa2a03459171c76bff45817330c10ef9f8af07011a33005b73b50189bbc7e71321480159061163557506040805180820190915260098152686165726f64726f6d6560b81b6020918201528151908201207fc570e6c17f57bc6841b1057f94fcf1785f440006714dbd98f64d859b54cd25d314155b1561165557806040516303622bc560e21b815260040161053891906133a5565b6040805180820190915260078152660756e69737761760cc1b6020918201528551908601207f5d5fcba6e8e389400ba7e8ccf3ef1060750f8fee5ccffa48c4afe76443818ece016116b3576116ae8484610bb88561239a565b611719565b6040805180820190915260098152686165726f64726f6d6560b81b6020918201528551908601207f3a8f193e80a84397be4efa806b030e87a0bbfff98eb2426709b27a64ab32da2d01611719576040516305fcd0f760e01b815260040160405180910390fd5b5050505050565b6002546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015611766573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178a91906133b7565b905090565b611797611ce0565b6001600160a01b0381166117c057604051631e4fbdf760e01b81525f6004820152602401610538565b6117c981611d0c565b50565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018590525f919087169063095ea7b3906044016020604051808303815f875af115801561183b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185f91906133ce565b5060408051610100810182526001600160a01b0388811682528781166020830190815262ffffff8681168486019081523060608601908152426080870190815260a087018c815260c088018c81525f60e08a01908152995163414bf38960e01b815289518916600482015296518816602488015293519094166044860152905185166064850152516084840152905160a48301525160c48201529251811660e484015290917f00000000000000000000000000000000000000000000000000000000000000009091169063414bf38990610104016020604051808303815f875af115801561194f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197391906133b7565b604080516001600160a01b038a811682528981166020830152918101889052606081018390529193507f000000000000000000000000000000000000000000000000000000000000000016907fad56699d0f375866eb895ed27203058a36a713382aaded78eb6b67da266d43329060800160405180910390a25095945050505050565b60015460405163095ea7b360e01b81526001600160a01b039182166004820152602481018390525f9184169063095ea7b3906044016020604051808303815f875af1158015611a47573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a6b91906133ce565b905080611aca5760405162461bcd60e51b815260206004820152602760248201527f417070726f76616c206f6620617373657420696e746f204161766520706f6f6c6044820152660819985a5b195960ca1b6064820152608401610538565b60015460405163617ba03760e01b81526001600160a01b038581166004830152602482018590523060448301525f60648301529091169063617ba037906084015f604051808303815f87803b158015611b21575f80fd5b505af1158015611b33573d5f803e3d5ffd5b505050507f76bfb501e0568602c59c0cffcde817c5bc2696480830199d9f8c115afe02c54e8383604051611b689291906133e7565b60405180910390a1505050565b60025460405163095ea7b360e01b81526001600160a01b039182166004820152602481018390525f9184169063095ea7b3906044016020604051808303815f875af1158015611bc6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bea91906133ce565b905080611c485760405162461bcd60e51b815260206004820152602660248201527f417070726f76616c206f6620617373657420696e746f20436f6d706f756e642060448201526519985a5b195960d21b6064820152608401610538565b600254604051634232cd6360e01b81523060048201526001600160a01b0385811660248301526044820185905290911690634232cd63906064015f604051808303815f87803b158015611c99575f80fd5b505af1158015611cab573d5f803e3d5ffd5b505050507f76bfb501e0568602c59c0cffcde817c5bc2696480830199d9f8c115afe02c54e8383604051611b6892919061341b565b5f546001600160a01b03163314610ac75760405163118cdaa760e01b8152336004820152602401610538565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f80611d656103f4565b5050505050905082811015611d8c5760405162461bcd60e51b815260040161053890613453565b600154604051631a4ca37b60e21b81526001600160a01b03868116600483015260248201869052306044830152909116906369328dec906064016020604051808303815f875af1158015611de2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e0691906133b7565b91507ff2119ac293790f480d31afd7d613930c9e10d9432d0dedb82738f50368fa27b58484604051611e399291906133e7565b60405180910390a15092915050565b5f80611e52611720565b905082811015611e745760405162461bcd60e51b815260040161053890613453565b6040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015611eb8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611edc91906133b7565b60025460405163f3fef3a360e01b81526001600160a01b0388811660048301526024820188905292935091169063f3fef3a3906044015f604051808303815f87803b158015611f29575f80fd5b505af1158015611f3b573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f92506001600160a01b03881691506370a0823190602401602060405180830381865afa158015611f83573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa791906133b7565b9050611fb3828261333c565b93507ff2119ac293790f480d31afd7d613930c9e10d9432d0dedb82738f50368fa27b58685604051611fe692919061341b565b60405180910390a150505092915050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828a8a886040518463ffffffff1660e01b8152600401612049939291906130f8565b602060405180830381865afa158015612064573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120889190613120565b90506001600160a01b0381166120b05760405162461bcd60e51b81526004016105389061313b565b5f80896001600160a01b03168b6001600160a01b0316106120d257898b6120d5565b8a8a5b915091505f826001600160a01b03168c6001600160a01b0316146120f957886120fb565b895b90505f836001600160a01b03168d6001600160a01b03161461211d578a61211f565b895b60405163095ea7b360e01b81526001600160a01b038781166004830152602482018590529192509085169063095ea7b3906044016020604051808303815f875af115801561216f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061219391906133ce565b5060405163095ea7b360e01b81526001600160a01b0386811660048301526024820183905284169063095ea7b3906044016020604051808303815f875af11580156121e0573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061220491906133ce565b505f856001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015612242573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122669190613187565b50505050505090505f6122788a612679565b90505f6122848a612679565b90506122938383838888612ab4565b98505f80896001600160a01b0316633c8a7d8d308f8f8f306040516020016122ca91906001600160a01b0391909116815260200190565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016122f9959493929190613495565b60408051808303815f875af1158015612314573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061233891906134e1565b91509150896001600160a01b03167fce0669c03a6bebf1a7a80046c110092cafdff0bb527ff2e4ea213faf8f07cf118a8a8e868660405161237d959493929190613503565b60405180910390a250505050505050505050979650505050505050565b604051630b4c774160e11b81525f906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631698ee82906123ec908890889088906004016130f8565b602060405180830381865afa158015612407573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061242b9190613120565b90506001600160a01b0381166124535760405162461bcd60e51b81526004016105389061313b565b5f80856001600160a01b0316876001600160a01b031610612475578587612478565b86865b915091505f80846001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156124ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124de9190613187565b5050505050915091505f6064826124f59190613228565b90505f612503836064613253565b60405163a34123a760e01b8152600284810b600483015282900b60248201526001600160801b038a1660448201529091505f9081906001600160a01b038a169063a34123a79060640160408051808303815f875af1158015612567573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061258b91906134e1565b6040516309e3d67b60e31b8152306004820152600287810b602483015286900b60448201526001600160801b0380841660648301528216608482015291935091506001600160a01b038a1690634f1eb3d89060a40160408051808303815f875af11580156125fb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261f919061353d565b5050886001600160a01b03167ff0c5c8e0b584b9430fbe397d62831fc7eca3e734a39a08659847de97469501de89898d8686604051612662959493929190613503565b60405180910390a250505050505050505050505050565b5f620d89e719600283900b128015906126a4575061269a620d89e71961356e565b60020b8260020b13155b6126df5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964207469636b60a01b6044820152606401610538565b5f808360020b126126f3578260020b612700565b8260020b6127009061358e565b90505f816001165f0361271757600160801b612729565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612768576080612763826ffff97272373d413259a46990580e213a6135a8565b901c90505b600482161561279257608061278d826ffff2e50f5f656932ef12357cf3c7fdcc6135a8565b901c90505b60088216156127bc5760806127b7826fffe5caca7e10e4e61c3624eaa0941cd06135a8565b901c90505b60108216156127e65760806127e1826fffcb9843d60f6159c9db58835c9266446135a8565b901c90505b602082161561281057608061280b826fff973b41fa98c081472e6896dfb254c06135a8565b901c90505b604082161561283a576080612835826fff2ea16466c96a3843ec78b326b528616135a8565b901c90505b608082161561286457608061285f826ffe5dee046a99a2a811c461f1969c30536135a8565b901c90505b61010082161561288f57608061288a826ffcbe86c7900a88aedcffc83b479aa3a46135a8565b901c90505b6102008216156128ba5760806128b5826ff987a7253ac413176f2b074cf7815e546135a8565b901c90505b6104008216156128e55760806128e0826ff3392b0822b70005940c7a398e4b70f36135a8565b901c90505b61080082161561291057608061290b826fe7159475a2c29b7443b29c7fa6e889d96135a8565b901c90505b61100082161561293b576080612936826fd097f3bdfd2022b8845ad8f792aa58256135a8565b901c90505b612000821615612966576080612961826fa9f746462d870fdf8a65dc1f90e061e56135a8565b901c90505b61400082161561299157608061298c826f70d869a156d2a1b890bb3df62baf32f76135a8565b901c90505b6180008216156129bc5760806129b7826f31be135f97d08fd981231505542fcfa66135a8565b901c90505b620100008216156129e85760806129e3826f09aa508b5b7a84e1c677de54f3e99bc96135a8565b901c90505b62020000821615612a13576080612a0e826e5d6af8dedb81196699c329225ee6046135a8565b901c90505b62040000821615612a3d576080612a38826d2216e584f5fa1ea926041bedfe986135a8565b901c90505b62080000821615612a65576080612a60826b048a170391f7dc42444e8fa26135a8565b901c90505b5f8460020b1315612a7e57612a7b815f196135d3565b90505b612a8d640100000000826135e6565b15612a99576001612a9b565b5f5b612aac9060ff16602083901c61334f565b949350505050565b5f836001600160a01b0316856001600160a01b03161115612ad3579293925b846001600160a01b0316866001600160a01b031611612afe57612af7858585612b75565b9050612b6c565b836001600160a01b0316866001600160a01b03161015612b5e575f612b24878686612b75565b90505f612b32878986612be8565b9050806001600160801b0316826001600160801b031610612b535780612b55565b815b92505050612b6c565b612b69858584612be8565b90505b95945050505050565b5f826001600160a01b0316846001600160a01b03161115612b94579192915b5f612bb6856001600160a01b0316856001600160a01b0316600160601b612c1d565b9050612bdd612bd88483612bca89896135f9565b6001600160a01b0316612c1d565b612d8c565b9150505b9392505050565b5f826001600160a01b0316846001600160a01b03161115612c07579192915b612aac612bd883600160601b612bca88886135f9565b5f80805f19858709858702925082811083820303915050805f03612c51575f8411612c46575f80fd5b508290049050612be1565b808411612c5c575f80fd5b5f848688098084039381119092039190505f612c7a8619600161334f565b8616958690049593849004935f819003046001019050612c9a81846135a8565b909317925f612caa8760036135a8565b6002189050612cb981886135a8565b612cc490600261333c565b612cce90826135a8565b9050612cda81886135a8565b612ce590600261333c565b612cef90826135a8565b9050612cfb81886135a8565b612d0690600261333c565b612d1090826135a8565b9050612d1c81886135a8565b612d2790600261333c565b612d3190826135a8565b9050612d3d81886135a8565b612d4890600261333c565b612d5290826135a8565b9050612d5e81886135a8565b612d6990600261333c565b612d7390826135a8565b9050612d7f81866135a8565b9998505050505050505050565b806001600160801b0381168114612da1575f80fd5b919050565b6001600160a01b03811681146117c9575f80fd5b803562ffffff81168114612da1575f80fd5b5f805f60608486031215612dde575f80fd5b8335612de981612da6565b92506020840135612df981612da6565b9150612e0760408501612dba565b90509250925092565b5f805f8060808587031215612e23575f80fd5b8435612e2e81612da6565b93506020850135612e3e81612da6565b925060408501359150612e5360608601612dba565b905092959194509250565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112612e81575f80fd5b813567ffffffffffffffff80821115612e9c57612e9c612e5e565b604051601f8301601f19908116603f01168101908282118183101715612ec457612ec4612e5e565b81604052838152866020858801011115612edc575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f60608486031215612f0d575f80fd5b833567ffffffffffffffff811115612f23575f80fd5b612f2f86828701612e72565b9350506020840135612f4081612da6565b929592945050506040919091013590565b5f60208284031215612f61575f80fd5b8135612be181612da6565b5f8060408385031215612f7d575f80fd5b8235612f8881612da6565b946020939093013593505050565b8060020b81146117c9575f80fd5b5f805f805f805f80610100898b031215612fbc575f80fd5b883567ffffffffffffffff811115612fd2575f80fd5b612fde8b828c01612e72565b9850506020890135612fef81612da6565b96506040890135612fff81612da6565b9550606089013594506080890135935061301b60a08a01612dba565b925060c089013561302b81612f96565b915060e089013561303b81612f96565b809150509295985092959890939650565b5f805f806080858703121561305f575f80fd5b843567ffffffffffffffff811115613075575f80fd5b61308187828801612e72565b945050602085013561309281612da6565b925060408501356130a281612da6565b9396929550929360600135925050565b5f805f805f8060c087890312156130c7575f80fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b6001600160a01b03938416815291909216602082015262ffffff909116604082015260600190565b5f60208284031215613130575f80fd5b8151612be181612da6565b602080825260129082015271141bdbdb08191bd95cdb89dd08195e1a5cdd60721b604082015260600190565b805161ffff81168114612da1575f80fd5b80518015158114612da1575f80fd5b5f805f805f805f60e0888a03121561319d575f80fd5b87516131a881612da6565b60208901519097506131b981612f96565b95506131c760408901613167565b94506131d560608901613167565b93506131e360808901613167565b925060a088015160ff811681146131f8575f80fd5b915061320660c08901613178565b905092959891949750929550565b634e487b7160e01b5f52601160045260245ffd5b600282810b9082900b03627fffff198112627fffff8213171561324d5761324d613214565b92915050565b600281810b9083900b01627fffff8113627fffff198212171561324d5761324d613214565b80516001600160801b0381168114612da1575f80fd5b5f805f805f60a086880312156132a2575f80fd5b6132ab86613278565b945060208601519350604086015192506132c760608701613278565b91506132d560808701613278565b90509295509295909350565b60208082526013908201527227b7363c9030b3b2b73a1037b91037bbb732b960691b604082015260600190565b602080825260149082015273496e73756666696369656e742062616c616e636560601b604082015260600190565b8181038181111561324d5761324d613214565b8082018082111561324d5761324d613214565b5f81518084525f5b818110156133865760208185018101518683018201520161336a565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f612be16020830184613362565b5f602082840312156133c7575f80fd5b5051919050565b5f602082840312156133de575f80fd5b612be182613178565b6060808252600490820152634161766560e01b60808201526001600160a01b03929092166020830152604082015260a00190565b60608082526008908201526710dbdb5c1bdd5b9960c21b60808201526001600160a01b03929092166020830152604082015260a00190565b60208082526022908201527f43616e6e6f74207769746864726177206d6f7265207468616e20626f72726f77604082015261195960f21b606082015260800190565b60018060a01b03861681528460020b60208201528360020b60408201526001600160801b038316606082015260a060808201525f6134d660a0830184613362565b979650505050505050565b5f80604083850312156134f2575f80fd5b505080516020909101519092909150565b6001600160a01b0395861681529390941660208401526001600160801b039190911660408301526060820152608081019190915260a00190565b5f806040838503121561354e575f80fd5b61355783613278565b915061356560208401613278565b90509250929050565b5f8160020b627fffff19810361358657613586613214565b5f0392915050565b5f600160ff1b82016135a2576135a2613214565b505f0390565b808202811582820484141761324d5761324d613214565b634e487b7160e01b5f52601260045260245ffd5b5f826135e1576135e16135bf565b500490565b5f826135f4576135f46135bf565b500690565b6001600160a01b0382811682821603908082111561361957613619613214565b509291505056fea2646970667358221220fb5c2a00a8ae482dd197a7a109c3db4fe86b2f56f8b951d4b352b1a7ef8a30c264736f6c63430008160033a2646970667358221220472810b03add19bec8ad27296ac8d04aea1e9f33c3e4da127d25eb27ddda164d64736f6c63430008160033", + "nonce": "0x1ec", + "chainId": "0x14a34" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x97af31", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x4f6a853d43237dcb7715e1e2e4a5dbf8c6483c200ea9d79eeacd6c3d54802ef4", + "transactionIndex": "0x33", + "blockHash": "0x081af5e84bb3796005fc2f4f01249b6262b696f53b2e9fecfe9f717fa8090e3a", + "blockNumber": "0x149eb1b", + "gasUsed": "0x3a1e42", + "effectiveGasPrice": "0xe5ce7", + "from": "0x12b2434a1022d5787bf06056f2885fe35de62bf8", + "to": null, + "contractAddress": "0x210088ae6ee018133791f20406bb239f1ea98379", + "l1BaseFeeScalar": "0x44d", + "l1BlobBaseFee": "0x1", + "l1BlobBaseFeeScalar": "0xa118b", + "l1Fee": "0x1a1084d7b8b", + "l1GasPrice": "0x2e0b84442", + "l1GasUsed": "0x20223" + } + ], + "libraries": [], + "pending": [], + "returns": { + "0": { + "internal_type": "contract VaultFactory", + "value": "0x210088AE6EE018133791f20406Bb239f1ea98379" + } + }, + "timestamp": 1739011371, + "chain": 84532, + "commit": "2319c6d" +} \ No newline at end of file diff --git a/broadcast/DeployVaultFactory.s.sol/84532/run-latest.json b/broadcast/DeployVaultFactory.s.sol/84532/run-latest.json index 66c62dd..3929e08 100644 --- a/broadcast/DeployVaultFactory.s.sol/84532/run-latest.json +++ b/broadcast/DeployVaultFactory.s.sol/84532/run-latest.json @@ -1,18 +1,18 @@ { "transactions": [ { - "hash": "0x4bcd3ea0a755da46d20fa618e7b7aa1bfb335bcb161203df48bb164193235b0d", + "hash": "0x4f6a853d43237dcb7715e1e2e4a5dbf8c6483c200ea9d79eeacd6c3d54802ef4", "transactionType": "CREATE", "contractName": "VaultFactory", - "contractAddress": "0xba31d235cf7f92f857fe891b630110efe1e47002", + "contractAddress": "0x210088ae6ee018133791f20406bb239f1ea98379", "function": null, "arguments": null, "transaction": { - "from": "0x7e393441edc1bb1621318e000cdfc74947f23b26", - "gas": "0x4c3b79", + "from": "0x12b2434a1022d5787bf06056f2885fe35de62bf8", + "gas": "0x4b8dbc", "value": "0x0", - "input": "0x6080604052600c805462ff00ff19166201000117905534801561002157600080fd5b506101546040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810191909152506040805161012081018252734200000000000000000000000000000000000006815273036cbd53842c5426634e7929541ec2318f3dcf7e602082015273fe45bf4def7223ab1bf83ca17a4462ef1647f7ff9181019190915273571621ce60cebb0c1d442b5afb38b1663c6bf0176060820152734752ba5dbc23f44d87826276bf6fd6b1c372ad2460808201527394cc0aac535ccdb3c01d6787d6413c739ae12bc460a082015273c5290058841028f1614f3a6f0f5816cad0df5e2760c082015273be781d7bdf469f3d94a62cdcc407ace106aeca7460e0820152604d61010082015290565b8051600e80546001600160a01b03199081166001600160a01b03938416179091556020830151600f8054831691841691909117905560408301516010805483169184169190911790556060830151601180548316918416919091179055608083015160128054831691841691909117905560a083015160138054831691841691909117905560c083015160148054831691841691909117905560e083015160158054831691841691909117905561010090920151601680549093169116179055614074806102236000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063989e6fd911610066578063989e6fd914610191578063b4bd6f4614610199578063d1a43bda146101ac578063d7b65745146101b4578063f8ccbf471461025257600080fd5b806347ae49e714610098578063522c441d1461012a57806358f674761461013257806365cacaa414610173575b600080fd5b6100a0610275565b604051610121919081516001600160a01b03908116825260208084015182169083015260408084015182169083015260608084015182169083015260808084015182169083015260a08084015182169083015260c08084015182169083015260e0808401518216908301526101009283015116918101919091526101200190565b60405180910390f35b6100a0610306565b61015b6101403660046106cf565b600d602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610121565b336000908152600d60205260409020546001600160a01b031661015b565b6100a06103a8565b61015b6101a73660046106cf565b61043b565b6100a061052a565b600e54600f546010546011546012546013546014546015546016546101f8986001600160a01b03908116988116978116968116958116948116938116928116911689565b604080516001600160a01b039a8b168152988a1660208a01529689169688019690965293871660608701529186166080860152851660a0850152841660c0840152831660e083015290911661010082015261012001610121565b600c546102659062010000900460ff1681565b6040519015158152602001610121565b61027d610676565b5060408051610120810182526000808252735425890298aed601595a70ab815c96711a31bc656020830152739cfcc1b289e59fbe1e769f020c77315df847376092820192909252606081018290526080810182905260a0810182905260c0810191909152738b9b2af4afb389b4a70a474dfd4adcd4a302bb4060e0820152604d61010082015290565b61030e610676565b50604080516101208101825273c558dbdd856501fcd9aaf1e62eae57a9f0629a3c81527394a9d9ac8a22534e3faca9f4e7f2e2cf85d5e4c86020820152600091810182905273e3e0106227181958abfba960c13d0fe52c73326560608201526080810182905260a0810182905260c0810191909152736ae43d3271ff6888e7fc43fd7321a503ff73895160e0820152604d61010082015290565b6103b0610676565b6103ee6040518060400160405280601881526020017f54657374696e67204f6e20416e76696c204e6574776f726b000000000000000081525061060b565b506040805161012081018252600080825260016020830152918101829052606081019190915260026080820152600360a0820152600660c0820152600760e0820152604d61010082015290565b601654601554601154601354601254604051600095869588956001600160a01b03928316959183169490831693918316921690610477906106c2565b6001600160a01b0396871681529486166020860152928516604085015290841660608401528316608083015290911660a082015260c001604051809103906000f0801580156104ca573d6000803e3d6000fd5b506001600160a01b038481166000818152600d602052604080822080546001600160a01b031916948616948517905551939450919290917f5d9c31ffa0fecffd7cf379989a3c7af252f0335e0d2a1320b55245912c781f5391a392915050565b610532610676565b5060408051610120810182526006602160991b01815273036cbd53842c5426634e7929541ec2318f3dcf7e602082015273fe45bf4def7223ab1bf83ca17a4462ef1647f7ff9181019190915273571621ce60cebb0c1d442b5afb38b1663c6bf0176060820152734752ba5dbc23f44d87826276bf6fd6b1c372ad2460808201527394cc0aac535ccdb3c01d6787d6413c739ae12bc460a082015273c5290058841028f1614f3a6f0f5816cad0df5e2760c082015273be781d7bdf469f3d94a62cdcc407ace106aeca7460e0820152604d61010082015290565b61064e8160405160240161061f91906106ff565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b179052610651565b50565b61064e8160006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915290565b6138f08061074f83390190565b6000602082840312156106e157600080fd5b81356001600160a01b03811681146106f857600080fd5b9392505050565b60006020808352835180602085015260005b8181101561072d57858101830151858201604001528201610711565b506000604082860101526040601f19601f830116850101925050509291505056fe60c06040523480156200001157600080fd5b50604051620038f0380380620038f0833981016040819052620000349162000139565b83838383896001600160a01b0381166200006857604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200007381620000cc565b50600180546001600160a01b039586166001600160a01b0319918216179091556002805494861694821694909417909355908316608052821660a052600380549790921696169590951790945550620001ba9350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200013457600080fd5b919050565b60008060008060008060c087890312156200015357600080fd5b6200015e876200011c565b95506200016e602088016200011c565b94506200017e604088016200011c565b93506200018e606088016200011c565b92506200019e608088016200011c565b9150620001ae60a088016200011c565b90509295509295509295565b60805160a0516136e66200020a60003960008181610289015281816104900152818161200d01526123da01526000818161024a015281816117c7015281816118ef015261198a01526136e66000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c8063a03e4bc3116100b8578063ca11615e1161007c578063ca11615e1461032e578063dc06618014610341578063e6e1bdec146103bb578063e8f6daa9146103c3578063f2fde38b146103d6578063f5ff5c76146103e957600080fd5b8063a03e4bc3146102cf578063a1db9782146102e2578063aab76479146102f5578063bcf685ed14610308578063c7d716d71461031b57600080fd5b8063715018a6116100ff578063715018a61461023d578063735de9f7146102455780638bdb2afa146102845780638da5cb5b146102ab57806397feb926146102bc57600080fd5b806321db82401461013c5780634a0de08f14610176578063592bac55146101ae5780635d631152146101cf5780635db8083e146101e4575b600080fd5b6101446103fc565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0015b60405180910390f35b610189610184366004612e1c565b610488565b604080516001600160801b03909416845260208401929092529082015260600161016d565b6101c16101bc366004612e63565b6106d9565b60405190815260200161016d565b6101e26101dd366004612f57565b6107bd565b005b6101f76101f2366004612fb1565b610a1f565b60405161016d919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080918201519181019190915260a00190565b6101e2610ab3565b61026c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161016d565b61026c7f000000000000000000000000000000000000000000000000000000000000000081565b6000546001600160a01b031661026c565b6101e26102ca366004612fce565b610ac7565b60015461026c906001600160a01b031681565b6101e26102f0366004612fce565b610cb5565b6101c1610303366004612f57565b610ecb565b6101e2610316366004612fb1565b6111d7565b6101e2610329366004613009565b611201565b6101e261033c3660046130b7565b61154f565b61038961034f366004612fb1565b6004602081905260009182526040909120805460018201546002830154600384015493909401546001600160a01b03909216939092909185565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a00161016d565b6101c1611700565b60025461026c906001600160a01b031681565b6101e26103e4366004612fb1565b611772565b60035461026c906001600160a01b031681565b600154604051632fe4a15f60e21b8152306004820152600091829182918291829182916001600160a01b039091169063bf92857c9060240160c060405180830381865afa158015610451573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104759190613121565b949b939a50919850965094509092509050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828888886040518463ffffffff1660e01b81526004016104de9392919061316b565b602060405180830381865afa1580156104fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051f9190613193565b90506001600160a01b0381166105505760405162461bcd60e51b8152600401610547906131b0565b60405180910390fd5b600080876001600160a01b0316896001600160a01b031610610573578789610576565b88885b91509150600080846001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156105bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105df91906131fe565b50505050509150915060006064826105f791906132a7565b905060006106068360646132d2565b6040516bffffffffffffffffffffffff193060601b16602082015260e884811b603483015282901b60378201529091506001600160a01b0388169063514ea4bf90603a01604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161067e91815260200190565b60a060405180830381865afa15801561069b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bf919061330e565b50929c50909a509850505050505050505093509350939050565b6003546000906001600160a01b031633146107065760405162461bcd60e51b815260040161054790613365565b6001600160a01b0385166000908152600460205260409020600101548311156107415760405162461bcd60e51b815260040161054790613389565b61074f8585856001866117b0565b6001600160a01b03861660009081526004602052604081206001018054929350859290919061077f9084906133b7565b90915550506001600160a01b038416600090815260046020526040812060010180548392906107af9084906133ca565b909155509095945050505050565b6003546001600160a01b031633146107e75760405162461bcd60e51b815260040161054790613365565b6040805180820190915260048152636161766560e01b60209182015283519084012083907fe0a39fef8aa5887c76606e7a14a5db8dc6676191e4866b2a609a3aa003b183291480159061087f575060408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528151908201207f2b05eae252b2d830081b9362c105fc1b4e5f974a0c53bee02c06419c2f4a117e14155b1561089f57806040516303622bc560e21b81526004016105479190613423565b6001600160a01b0383166000908152600460205260409020600101548211156108da5760405162461bcd60e51b815260040161054790613389565b6040805180820190915260048152636161766560e01b6020918201528451908501207f1f5c6010755a7783899f9185eb5a247239989e6e1b7994d59f65c55ffc4e7cd7016109625761092c83836119e2565b6001600160a01b038316600090815260046020526040812060020180548492906109579084906133ca565b909155506109e99050565b60408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528451908501207fd4fa151dad4d27cff7e46c9d3efa03e4b1a068b5f3ac411fd3f9be63d0b5ee82016109e9576109b88383611b6b565b6001600160a01b038316600090815260046020526040812060030180548492906109e39084906133ca565b90915550505b6001600160a01b03831660009081526004602052604081206001018054849290610a149084906133b7565b909155505050505050565b610a5a6040518060a0016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b03908116600090815260046020818152604092839020835160a08101855281549095168552600181015491850191909152600281015492840192909252600382015460608401520154608082015290565b610abb611cdf565b610ac56000611d0c565b565b610acf611cdf565b604051636eb1769f60e11b815233600482015230602482015281906001600160a01b0384169063dd62ed3e90604401602060405180830381865afa158015610b1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3f9190613436565b1015610b865760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610547565b6040516323b872dd60e01b8152336004820152306024820152604481018290526000906001600160a01b038416906323b872dd906064016020604051808303816000875af1158015610bdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c00919061344f565b905080610c415760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610547565b6001600160a01b03831660009081526004602052604081206001018054849290610c6c9084906133ca565b90915550506040518281526001600160a01b038416907fab79632de7fe1724598ce2214eaa326d90d48064d2d3397406ecc5769316a5f6906020015b60405180910390a2505050565b610cbd611cdf565b6001600160a01b038216600090815260046020526040902060010154811115610cf85760405162461bcd60e51b815260040161054790613389565b816001600160a01b031663095ea7b3610d196000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015610d66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8a919061344f565b506000826001600160a01b031663a9059cbb610dae6000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af1158015610dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1f919061344f565b905080610e605760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610547565b6001600160a01b03831660009081526004602052604081206001018054849290610e8b9084906133b7565b90915550506040518281526001600160a01b038416907f7e2c99819371db0a6fc6f4269fe872496e44f502df19ba3eae594b7a1598746090602001610ca8565b6003546000906001600160a01b03163314610ef85760405162461bcd60e51b815260040161054790613365565b6040805180820190915260048152636161766560e01b60209182015284519085012084907fe0a39fef8aa5887c76606e7a14a5db8dc6676191e4866b2a609a3aa003b1832914801590610f90575060408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528151908201207f2b05eae252b2d830081b9362c105fc1b4e5f974a0c53bee02c06419c2f4a117e14155b15610fb057806040516303622bc560e21b81526004016105479190613423565b6040805180820190915260048152636161766560e01b6020918201528551908601207f1f5c6010755a7783899f9185eb5a247239989e6e1b7994d59f65c55ffc4e7cd7016110a8576001600160a01b0384166000908152600460205260409020600201548311156110635760405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e7420696e76657374656420616d6f756e74000000006044820152606401610547565b61106d8484611d5c565b6001600160a01b03851660009081526004602052604081206002018054929450859290919061109d9084906133b7565b9091555061119f9050565b60408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528551908601207fd4fa151dad4d27cff7e46c9d3efa03e4b1a068b5f3ac411fd3f9be63d0b5ee820161119f576001600160a01b03841660009081526004602052604090206003015483111561115f5760405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e7420696e76657374656420616d6f756e74000000006044820152606401610547565b6111698484611e4d565b6001600160a01b0385166000908152600460205260408120600301805492945085929091906111999084906133b7565b90915550505b6001600160a01b038416600090815260046020526040812060010180548492906111ca9084906133ca565b9091555050509392505050565b6111df611cdf565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331461122b5760405162461bcd60e51b815260040161054790613365565b6040805180820190915260078152660756e69737761760cc1b60209182015288519089012088907fa2a03459171c76bff45817330c10ef9f8af07011a33005b73b50189bbc7e7132148015906112c757506040805180820190915260098152686165726f64726f6d6560b81b6020918201528151908201207fc570e6c17f57bc6841b1057f94fcf1785f440006714dbd98f64d859b54cd25d314155b156112e757806040516303622bc560e21b81526004016105479190613423565b6001600160a01b0388166000908152600460205260409020600101548611156113525760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e742062616c616e636520746f6b656e3000000000006044820152606401610547565b6001600160a01b0387166000908152600460205260409020600101548511156113bd5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e742062616c616e636520746f6b656e3100000000006044820152606401610547565b6040805180820190915260078152660756e69737761760cc1b6020918201528951908a01207f5d5fcba6e8e389400ba7e8ccf3ef1060750f8fee5ccffa48c4afe76443818ece0161147e5761141788888888888888612008565b506001600160a01b038816600090815260046020819052604082200180548892906114439084906133ca565b90915550506001600160a01b038716600090815260046020819052604082200180548792906114739084906133ca565b909155506114e49050565b6040805180820190915260098152686165726f64726f6d6560b81b6020918201528951908a01207f3a8f193e80a84397be4efa806b030e87a0bbfff98eb2426709b27a64ab32da2d016114e4576040516305fcd0f760e01b815260040160405180910390fd5b6001600160a01b0388166000908152600460205260408120600101805488929061150f9084906133b7565b90915550506001600160a01b0387166000908152600460205260408120600101805487929061153f9084906133b7565b9091555050505050505050505050565b6003546001600160a01b031633146115795760405162461bcd60e51b815260040161054790613365565b6040805180820190915260078152660756e69737761760cc1b60209182015284519085012084907fa2a03459171c76bff45817330c10ef9f8af07011a33005b73b50189bbc7e71321480159061161557506040805180820190915260098152686165726f64726f6d6560b81b6020918201528151908201207fc570e6c17f57bc6841b1057f94fcf1785f440006714dbd98f64d859b54cd25d314155b1561163557806040516303622bc560e21b81526004016105479190613423565b6040805180820190915260078152660756e69737761760cc1b6020918201528551908601207f5d5fcba6e8e389400ba7e8ccf3ef1060750f8fee5ccffa48c4afe76443818ece016116935761168e8484610bb8856123c0565b6116f9565b6040805180820190915260098152686165726f64726f6d6560b81b6020918201528551908601207f3a8f193e80a84397be4efa806b030e87a0bbfff98eb2426709b27a64ab32da2d016116f9576040516305fcd0f760e01b815260040160405180910390fd5b5050505050565b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176d9190613436565b905090565b61177a611cdf565b6001600160a01b0381166117a457604051631e4fbdf760e01b815260006004820152602401610547565b6117ad81611d0c565b50565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018590526000919087169063095ea7b3906044016020604051808303816000875af1158015611823573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611847919061344f565b5060408051610100810182526001600160a01b0388811682528781166020830190815262ffffff8681168486019081523060608601908152426080870190815260a087018c815260c088018c8152600060e08a01908152995163414bf38960e01b815289518916600482015296518816602488015293519094166044860152905185166064850152516084840152905160a48301525160c48201529251811660e484015290917f00000000000000000000000000000000000000000000000000000000000000009091169063414bf38990610104016020604051808303816000875af115801561193b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195f9190613436565b604080516001600160a01b038a811682528981166020830152918101889052606081018390529193507f000000000000000000000000000000000000000000000000000000000000000016907fad56699d0f375866eb895ed27203058a36a713382aaded78eb6b67da266d43329060800160405180910390a25095945050505050565b60015460405163095ea7b360e01b81526001600160a01b0391821660048201526024810183905260009184169063095ea7b3906044016020604051808303816000875af1158015611a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5b919061344f565b905080611aba5760405162461bcd60e51b815260206004820152602760248201527f417070726f76616c206f6620617373657420696e746f204161766520706f6f6c6044820152660819985a5b195960ca1b6064820152608401610547565b60015460405163617ba03760e01b81526001600160a01b03858116600483015260248201859052306044830152600060648301529091169063617ba03790608401600060405180830381600087803b158015611b1557600080fd5b505af1158015611b29573d6000803e3d6000fd5b505050507f76bfb501e0568602c59c0cffcde817c5bc2696480830199d9f8c115afe02c54e8383604051611b5e92919061346a565b60405180910390a1505050565b60025460405163095ea7b360e01b81526001600160a01b0391821660048201526024810183905260009184169063095ea7b3906044016020604051808303816000875af1158015611bc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be4919061344f565b905080611c425760405162461bcd60e51b815260206004820152602660248201527f417070726f76616c206f6620617373657420696e746f20436f6d706f756e642060448201526519985a5b195960d21b6064820152608401610547565b600254604051634232cd6360e01b81523060048201526001600160a01b0385811660248301526044820185905290911690634232cd6390606401600060405180830381600087803b158015611c9657600080fd5b505af1158015611caa573d6000803e3d6000fd5b505050507f76bfb501e0568602c59c0cffcde817c5bc2696480830199d9f8c115afe02c54e8383604051611b5e92919061349e565b6000546001600160a01b03163314610ac55760405163118cdaa760e01b8152336004820152602401610547565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080611d676103fc565b5050505050905082811015611d8e5760405162461bcd60e51b8152600401610547906134d6565b600154604051631a4ca37b60e21b81526001600160a01b03868116600483015260248201869052306044830152909116906369328dec906064016020604051808303816000875af1158015611de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e0b9190613436565b91507ff2119ac293790f480d31afd7d613930c9e10d9432d0dedb82738f50368fa27b58484604051611e3e92919061346a565b60405180910390a15092915050565b600080611e58611700565b905082811015611e7a5760405162461bcd60e51b8152600401610547906134d6565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015611ec1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee59190613436565b60025460405163f3fef3a360e01b81526001600160a01b0388811660048301526024820188905292935091169063f3fef3a390604401600060405180830381600087803b158015611f3557600080fd5b505af1158015611f49573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092506001600160a01b03881691506370a0823190602401602060405180830381865afa158015611f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb89190613436565b9050611fc482826133b7565b93507ff2119ac293790f480d31afd7d613930c9e10d9432d0dedb82738f50368fa27b58685604051611ff792919061349e565b60405180910390a150505092915050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828a8a886040518463ffffffff1660e01b815260040161205b9392919061316b565b602060405180830381865afa158015612078573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209c9190613193565b90506001600160a01b0381166120c45760405162461bcd60e51b8152600401610547906131b0565b600080896001600160a01b03168b6001600160a01b0316106120e757898b6120ea565b8a8a5b915091506000826001600160a01b03168c6001600160a01b03161461210f5788612111565b895b90506000836001600160a01b03168d6001600160a01b031614612134578a612136565b895b60405163095ea7b360e01b81526001600160a01b038781166004830152602482018590529192509085169063095ea7b3906044016020604051808303816000875af1158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad919061344f565b5060405163095ea7b360e01b81526001600160a01b0386811660048301526024820183905284169063095ea7b3906044016020604051808303816000875af11580156121fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612221919061344f565b506000856001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015612262573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228691906131fe565b505050505050905060006122998a6126af565b905060006122a68a6126af565b90506122b58383838888612af1565b9850600080896001600160a01b0316633c8a7d8d308f8f8f306040516020016122ed91906001600160a01b0391909116815260200190565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161231c959493929190613518565b60408051808303816000875af115801561233a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235e9190613565565b91509150896001600160a01b03167fce0669c03a6bebf1a7a80046c110092cafdff0bb527ff2e4ea213faf8f07cf118a8a8e86866040516123a3959493929190613589565b60405180910390a250505050505050505050979650505050505050565b604051630b4c774160e11b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631698ee82906124139088908890889060040161316b565b602060405180830381865afa158015612430573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124549190613193565b90506001600160a01b03811661247c5760405162461bcd60e51b8152600401610547906131b0565b600080856001600160a01b0316876001600160a01b03161061249f5785876124a2565b86865b91509150600080846001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156124e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250b91906131fe565b505050505091509150600060648261252391906132a7565b905060006125328360646132d2565b60405163a34123a760e01b8152600284810b600483015282900b60248201526001600160801b038a16604482015290915060009081906001600160a01b038a169063a34123a79060640160408051808303816000875af115801561259a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125be9190613565565b6040516309e3d67b60e31b8152306004820152600287810b602483015286900b60448201526001600160801b0380841660648301528216608482015291935091506001600160a01b038a1690634f1eb3d89060a40160408051808303816000875af1158015612631573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265591906135c3565b5050886001600160a01b03167ff0c5c8e0b584b9430fbe397d62831fc7eca3e734a39a08659847de97469501de89898d8686604051612698959493929190613589565b60405180910390a250505050505050505050505050565b6000620d89e719600283900b128015906126db57506126d1620d89e7196135f6565b60020b8260020b13155b6127165760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964207469636b60a01b6044820152606401610547565b6000808360020b1261272b578260020b612738565b8260020b61273890613618565b905060008160011660000361275157600160801b612763565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156127a257608061279d826ffff97272373d413259a46990580e213a613634565b901c90505b60048216156127cc5760806127c7826ffff2e50f5f656932ef12357cf3c7fdcc613634565b901c90505b60088216156127f65760806127f1826fffe5caca7e10e4e61c3624eaa0941cd0613634565b901c90505b601082161561282057608061281b826fffcb9843d60f6159c9db58835c926644613634565b901c90505b602082161561284a576080612845826fff973b41fa98c081472e6896dfb254c0613634565b901c90505b604082161561287457608061286f826fff2ea16466c96a3843ec78b326b52861613634565b901c90505b608082161561289e576080612899826ffe5dee046a99a2a811c461f1969c3053613634565b901c90505b6101008216156128c95760806128c4826ffcbe86c7900a88aedcffc83b479aa3a4613634565b901c90505b6102008216156128f45760806128ef826ff987a7253ac413176f2b074cf7815e54613634565b901c90505b61040082161561291f57608061291a826ff3392b0822b70005940c7a398e4b70f3613634565b901c90505b61080082161561294a576080612945826fe7159475a2c29b7443b29c7fa6e889d9613634565b901c90505b611000821615612975576080612970826fd097f3bdfd2022b8845ad8f792aa5825613634565b901c90505b6120008216156129a057608061299b826fa9f746462d870fdf8a65dc1f90e061e5613634565b901c90505b6140008216156129cb5760806129c6826f70d869a156d2a1b890bb3df62baf32f7613634565b901c90505b6180008216156129f65760806129f1826f31be135f97d08fd981231505542fcfa6613634565b901c90505b62010000821615612a22576080612a1d826f09aa508b5b7a84e1c677de54f3e99bc9613634565b901c90505b62020000821615612a4d576080612a48826e5d6af8dedb81196699c329225ee604613634565b901c90505b62040000821615612a77576080612a72826d2216e584f5fa1ea926041bedfe98613634565b901c90505b62080000821615612a9f576080612a9a826b048a170391f7dc42444e8fa2613634565b901c90505b60008460020b1315612aba57612ab781600019613661565b90505b612ac964010000000082613675565b15612ad5576001612ad8565b60005b612ae99060ff16602083901c6133ca565b949350505050565b6000836001600160a01b0316856001600160a01b03161115612b11579293925b846001600160a01b0316866001600160a01b031611612b3c57612b35858585612bb5565b9050612bac565b836001600160a01b0316866001600160a01b03161015612b9e576000612b63878686612bb5565b90506000612b72878986612c2a565b9050806001600160801b0316826001600160801b031610612b935780612b95565b815b92505050612bac565b612ba9858584612c2a565b90505b95945050505050565b6000826001600160a01b0316846001600160a01b03161115612bd5579192915b6000612bf8856001600160a01b0316856001600160a01b0316600160601b612c60565b9050612c1f612c1a8483612c0c8989613689565b6001600160a01b0316612c60565b612dd9565b9150505b9392505050565b6000826001600160a01b0316846001600160a01b03161115612c4a579192915b612ae9612c1a83600160601b612c0c8888613689565b6000808060001985870985870292508281108382030391505080600003612c995760008411612c8e57600080fd5b508290049050612c23565b808411612ca557600080fd5b6000848688098084039381119092039190506000612cc5861960016133ca565b8616958690049593849004936000819003046001019050612ce68184613634565b909317926000612cf7876003613634565b6002189050612d068188613634565b612d119060026133b7565b612d1b9082613634565b9050612d278188613634565b612d329060026133b7565b612d3c9082613634565b9050612d488188613634565b612d539060026133b7565b612d5d9082613634565b9050612d698188613634565b612d749060026133b7565b612d7e9082613634565b9050612d8a8188613634565b612d959060026133b7565b612d9f9082613634565b9050612dab8188613634565b612db69060026133b7565b612dc09082613634565b9050612dcc8186613634565b9998505050505050505050565b806001600160801b0381168114612def57600080fd5b919050565b6001600160a01b03811681146117ad57600080fd5b803562ffffff81168114612def57600080fd5b600080600060608486031215612e3157600080fd5b8335612e3c81612df4565b92506020840135612e4c81612df4565b9150612e5a60408501612e09565b90509250925092565b60008060008060808587031215612e7957600080fd5b8435612e8481612df4565b93506020850135612e9481612df4565b925060408501359150612ea960608601612e09565b905092959194509250565b634e487b7160e01b600052604160045260246000fd5b600082601f830112612edb57600080fd5b813567ffffffffffffffff80821115612ef657612ef6612eb4565b604051601f8301601f19908116603f01168101908282118183101715612f1e57612f1e612eb4565b81604052838152866020858801011115612f3757600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215612f6c57600080fd5b833567ffffffffffffffff811115612f8357600080fd5b612f8f86828701612eca565b9350506020840135612fa081612df4565b929592945050506040919091013590565b600060208284031215612fc357600080fd5b8135612c2381612df4565b60008060408385031215612fe157600080fd5b8235612fec81612df4565b946020939093013593505050565b8060020b81146117ad57600080fd5b600080600080600080600080610100898b03121561302657600080fd5b883567ffffffffffffffff81111561303d57600080fd5b6130498b828c01612eca565b985050602089013561305a81612df4565b9650604089013561306a81612df4565b9550606089013594506080890135935061308660a08a01612e09565b925060c089013561309681612ffa565b915060e08901356130a681612ffa565b809150509295985092959890939650565b600080600080608085870312156130cd57600080fd5b843567ffffffffffffffff8111156130e457600080fd5b6130f087828801612eca565b945050602085013561310181612df4565b9250604085013561311181612df4565b9396929550929360600135925050565b60008060008060008060c0878903121561313a57600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b6001600160a01b03938416815291909216602082015262ffffff909116604082015260600190565b6000602082840312156131a557600080fd5b8151612c2381612df4565b602080825260129082015271141bdbdb08191bd95cdb89dd08195e1a5cdd60721b604082015260600190565b805161ffff81168114612def57600080fd5b80518015158114612def57600080fd5b600080600080600080600060e0888a03121561321957600080fd5b875161322481612df4565b602089015190975061323581612ffa565b9550613243604089016131dc565b9450613251606089016131dc565b935061325f608089016131dc565b925060a088015160ff8116811461327557600080fd5b915061328360c089016131ee565b905092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b600282810b9082900b03627fffff198112627fffff821317156132cc576132cc613291565b92915050565b600281810b9083900b01627fffff8113627fffff19821217156132cc576132cc613291565b80516001600160801b0381168114612def57600080fd5b600080600080600060a0868803121561332657600080fd5b61332f866132f7565b9450602086015193506040860151925061334b606087016132f7565b9150613359608087016132f7565b90509295509295909350565b6020808252600a908201526913db9b1e481859d95b9d60b21b604082015260600190565b602080825260149082015273496e73756666696369656e742062616c616e636560601b604082015260600190565b818103818111156132cc576132cc613291565b808201808211156132cc576132cc613291565b6000815180845260005b81811015613403576020818501810151868301820152016133e7565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612c2360208301846133dd565b60006020828403121561344857600080fd5b5051919050565b60006020828403121561346157600080fd5b612c23826131ee565b6060808252600490820152634161766560e01b60808201526001600160a01b03929092166020830152604082015260a00190565b60608082526008908201526710dbdb5c1bdd5b9960c21b60808201526001600160a01b03929092166020830152604082015260a00190565b60208082526022908201527f43616e6e6f74207769746864726177206d6f7265207468616e20626f72726f77604082015261195960f21b606082015260800190565b60018060a01b03861681528460020b60208201528360020b60408201526001600160801b038316606082015260a06080820152600061355a60a08301846133dd565b979650505050505050565b6000806040838503121561357857600080fd5b505080516020909101519092909150565b6001600160a01b0395861681529390941660208401526001600160801b039190911660408301526060820152608081019190915260a00190565b600080604083850312156135d657600080fd5b6135df836132f7565b91506135ed602084016132f7565b90509250929050565b60008160020b627fffff19810361360f5761360f613291565b60000392915050565b6000600160ff1b820161362d5761362d613291565b5060000390565b80820281158282048414176132cc576132cc613291565b634e487b7160e01b600052601260045260246000fd5b6000826136705761367061364b565b500490565b6000826136845761368461364b565b500690565b6001600160a01b038281168282160390808211156136a9576136a9613291565b509291505056fea2646970667358221220a3e658e993430ca9253841754cb27b4fca331c7c702af9bee59b01b0c2eccc4564736f6c63430008160033a2646970667358221220de6f151a0a324d3d7baddd11cfe6c03608330881e9115e4188f3d0d0db83074064736f6c63430008160033", - "nonce": "0x1", + "input": "0x6080604052600c805462ff00ff191662010001179055348015610020575f80fd5b5061015260408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810191909152506040805161012081018252734200000000000000000000000000000000000006815273036cbd53842c5426634e7929541ec2318f3dcf7e602082015273fe45bf4def7223ab1bf83ca17a4462ef1647f7ff9181019190915273571621ce60cebb0c1d442b5afb38b1663c6bf0176060820152734752ba5dbc23f44d87826276bf6fd6b1c372ad2460808201527394cc0aac535ccdb3c01d6787d6413c739ae12bc460a082015273c5290058841028f1614f3a6f0f5816cad0df5e2760c082015273be781d7bdf469f3d94a62cdcc407ace106aeca7460e0820152604d61010082015290565b8051600e80546001600160a01b03199081166001600160a01b03938416179091556020830151600f8054831691841691909117905560408301516010805483169184169190911790556060830151601180548316918416919091179055608083015160128054831691841691909117905560a083015160138054831691841691909117905560c083015160148054831691841691909117905560e083015160158054831691841691909117905561010090920151601680549093169116179055613fc18061021f5f395ff3fe608060405234801561000f575f80fd5b5060043610610090575f3560e01c8063989e6fd911610063578063989e6fd91461018b578063b4bd6f4614610193578063d1a43bda146101a6578063d7b65745146101ae578063f8ccbf471461024c575f80fd5b806347ae49e714610094578063522c441d1461012657806358f674761461012e57806365cacaa41461016e575b5f80fd5b61009c61026f565b60405161011d919081516001600160a01b03908116825260208084015182169083015260408084015182169083015260608084015182169083015260808084015182169083015260a08084015182169083015260c08084015182169083015260e0808401518216908301526101009283015116918101919091526101200190565b60405180910390f35b61009c6102ff565b61015661013c3660046106be565b600d6020525f90815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161011d565b335f908152600d60205260409020546001600160a01b0316610156565b61009c6103a0565b6101566101a13660046106be565b610432565b61009c61051c565b600e54600f546010546011546012546013546014546015546016546101f2986001600160a01b03908116988116978116968116958116948116938116928116911689565b604080516001600160a01b039a8b168152988a1660208a01529689169688019690965293871660608701529186166080860152851660a0850152841660c0840152831660e08301529091166101008201526101200161011d565b600c5461025f9062010000900460ff1681565b604051901515815260200161011d565b610277610666565b5060408051610120810182525f808252735425890298aed601595a70ab815c96711a31bc656020830152739cfcc1b289e59fbe1e769f020c77315df847376092820192909252606081018290526080810182905260a0810182905260c0810191909152738b9b2af4afb389b4a70a474dfd4adcd4a302bb4060e0820152604d61010082015290565b610307610666565b50604080516101208101825273c558dbdd856501fcd9aaf1e62eae57a9f0629a3c81527394a9d9ac8a22534e3faca9f4e7f2e2cf85d5e4c860208201525f91810182905273e3e0106227181958abfba960c13d0fe52c73326560608201526080810182905260a0810182905260c0810191909152736ae43d3271ff6888e7fc43fd7321a503ff73895160e0820152604d61010082015290565b6103a8610666565b6103e66040518060400160405280601881526020017f54657374696e67204f6e20416e76696c204e6574776f726b00000000000000008152506105fd565b5060408051610120810182525f80825260016020830152918101829052606081019190915260026080820152600360a0820152600660c0820152600760e0820152604d61010082015290565b6016546015546011546013546012546040515f95869588956001600160a01b0392831695918316949083169391831692169061046d906106b1565b6001600160a01b0396871681529486166020860152928516604085015290841660608401528316608083015290911660a082015260c001604051809103905ff0801580156104bd573d5f803e3d5ffd5b506001600160a01b038481165f818152600d602052604080822080546001600160a01b031916948616948517905551939450919290917f5d9c31ffa0fecffd7cf379989a3c7af252f0335e0d2a1320b55245912c781f5391a392915050565b610524610666565b5060408051610120810182526006602160991b01815273036cbd53842c5426634e7929541ec2318f3dcf7e602082015273fe45bf4def7223ab1bf83ca17a4462ef1647f7ff9181019190915273571621ce60cebb0c1d442b5afb38b1663c6bf0176060820152734752ba5dbc23f44d87826276bf6fd6b1c372ad2460808201527394cc0aac535ccdb3c01d6787d6413c739ae12bc460a082015273c5290058841028f1614f3a6f0f5816cad0df5e2760c082015273be781d7bdf469f3d94a62cdcc407ace106aeca7460e0820152604d61010082015290565b6106408160405160240161061191906106eb565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b179052610643565b50565b610640815f6a636f6e736f6c652e6c6f6790505f80835160208501845afa505050565b60408051610120810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915290565b6138548061073883390190565b5f602082840312156106ce575f80fd5b81356001600160a01b03811681146106e4575f80fd5b9392505050565b5f602080835283518060208501525f5b81811015610717578581018301518582016040015282016106fb565b505f604082860101526040601f19601f830116850101925050509291505056fe60c060405234801562000010575f80fd5b506040516200385438038062003854833981016040819052620000339162000135565b83838383896001600160a01b0381166200006657604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6200007181620000ca565b50600180546001600160a01b039586166001600160a01b0319918216179091556002805494861694821694909417909355908316608052821660a052600380549790921696169590951790945550620001b29350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811462000130575f80fd5b919050565b5f805f805f8060c087890312156200014b575f80fd5b620001568762000119565b9550620001666020880162000119565b9450620001766040880162000119565b9350620001866060880162000119565b9250620001966080880162000119565b9150620001a660a0880162000119565b90509295509295509295565b60805160a051613656620001fe5f395f81816102830152818161048301528181611ffb01526123b301525f8181610244015281816117e301528181611906015261199e01526136565ff3fe608060405234801561000f575f80fd5b5060043610610132575f3560e01c8063a03e4bc3116100b4578063ca11615e11610079578063ca11615e14610327578063dc0661801461033a578063e6e1bdec146103b3578063e8f6daa9146103bb578063f2fde38b146103ce578063f5ff5c76146103e1575f80fd5b8063a03e4bc3146102c8578063a1db9782146102db578063aab76479146102ee578063bcf685ed14610301578063c7d716d714610314575f80fd5b8063715018a6116100fa578063715018a614610237578063735de9f71461023f5780638bdb2afa1461027e5780638da5cb5b146102a557806397feb926146102b5575f80fd5b806321db8240146101365780634a0de08f14610170578063592bac55146101a85780635d631152146101c9578063604e3706146101de575b5f80fd5b61013e6103f4565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0015b60405180910390f35b61018361017e366004612dcc565b61047d565b604080516001600160801b039094168452602084019290925290820152606001610167565b6101bb6101b6366004612e10565b6106c2565b604051908152602001610167565b6101dc6101d7366004612efb565b6107b6565b005b6101f16101ec366004612f51565b610a28565b604051610167919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080918201519181019190915260a00190565b6101dc610ab6565b6102667f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610167565b6102667f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b0316610266565b6101dc6102c3366004612f6c565b610ac9565b600154610266906001600160a01b031681565b6101dc6102e9366004612f6c565b610cb0565b6101bb6102fc366004612efb565b610ebb565b6101dc61030f366004612f51565b6111d5565b6101dc610322366004612fa4565b6111ff565b6101dc61033536600461304c565b61155b565b610381610348366004612f51565b600460208190525f9182526040909120805460018201546002830154600384015493909401546001600160a01b03909216939092909185565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a001610167565b6101bb611720565b600254610266906001600160a01b031681565b6101dc6103dc366004612f51565b61178f565b600354610266906001600160a01b031681565b600154604051632fe4a15f60e21b81523060048201525f91829182918291829182916001600160a01b039091169063bf92857c9060240160c060405180830381865afa158015610446573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061046a91906130b2565b949b939a50919850965094509092509050565b5f805f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828888886040518463ffffffff1660e01b81526004016104d1939291906130f8565b602060405180830381865afa1580156104ec573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105109190613120565b90506001600160a01b0381166105415760405162461bcd60e51b81526004016105389061313b565b60405180910390fd5b5f80876001600160a01b0316896001600160a01b031610610563578789610566565b88885b915091505f80846001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156105a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105cc9190613187565b5050505050915091505f6064826105e39190613228565b90505f6105f1836064613253565b6040516bffffffffffffffffffffffff193060601b16602082015260e884811b603483015282901b60378201529091506001600160a01b0388169063514ea4bf90603a01604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161066991815260200190565b60a060405180830381865afa158015610684573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106a8919061328e565b50929c50909a509850505050505050505093509350939050565b6003545f906001600160a01b03163314806106e657505f546001600160a01b031633145b6107025760405162461bcd60e51b8152600401610538906132e1565b6001600160a01b0385165f9081526004602052604090206001015483111561073c5760405162461bcd60e51b81526004016105389061330e565b61074a8585856001866117cc565b6001600160a01b0386165f9081526004602052604081206001018054929350859290919061077990849061333c565b90915550506001600160a01b0384165f90815260046020526040812060010180548392906107a890849061334f565b909155509095945050505050565b6003546001600160a01b03163314806107d857505f546001600160a01b031633145b6107f45760405162461bcd60e51b8152600401610538906132e1565b6040805180820190915260048152636161766560e01b60209182015283519084012083907fe0a39fef8aa5887c76606e7a14a5db8dc6676191e4866b2a609a3aa003b183291480159061088c575060408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528151908201207f2b05eae252b2d830081b9362c105fc1b4e5f974a0c53bee02c06419c2f4a117e14155b156108ac57806040516303622bc560e21b815260040161053891906133a5565b6001600160a01b0383165f908152600460205260409020600101548211156108e65760405162461bcd60e51b81526004016105389061330e565b6040805180820190915260048152636161766560e01b6020918201528451908501207f1f5c6010755a7783899f9185eb5a247239989e6e1b7994d59f65c55ffc4e7cd70161096d5761093883836119f6565b6001600160a01b0383165f908152600460205260408120600201805484929061096290849061334f565b909155506109f39050565b60408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528451908501207fd4fa151dad4d27cff7e46c9d3efa03e4b1a068b5f3ac411fd3f9be63d0b5ee82016109f3576109c38383611b75565b6001600160a01b0383165f90815260046020526040812060030180548492906109ed90849061334f565b90915550505b6001600160a01b0383165f9081526004602052604081206001018054849290610a1d90849061333c565b909155505050505050565b610a5e6040518060a001604052805f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b506001600160a01b039081165f90815260046020818152604092839020835160a08101855281549095168552600181015491850191909152600281015492840192909252600382015460608401520154608082015290565b610abe611ce0565b610ac75f611d0c565b565b610ad1611ce0565b604051636eb1769f60e11b815233600482015230602482015281906001600160a01b0384169063dd62ed3e90604401602060405180830381865afa158015610b1b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3f91906133b7565b1015610b865760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610538565b6040516323b872dd60e01b8152336004820152306024820152604481018290525f906001600160a01b038416906323b872dd906064016020604051808303815f875af1158015610bd8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bfc91906133ce565b905080610c3d5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610538565b6001600160a01b0383165f9081526004602052604081206001018054849290610c6790849061334f565b90915550506040518281526001600160a01b038416907fab79632de7fe1724598ce2214eaa326d90d48064d2d3397406ecc5769316a5f6906020015b60405180910390a2505050565b610cb8611ce0565b6001600160a01b0382165f90815260046020526040902060010154811115610cf25760405162461bcd60e51b81526004016105389061330e565b816001600160a01b031663095ea7b3610d125f546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af1158015610d5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d8091906133ce565b505f826001600160a01b031663a9059cbb610da25f546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303815f875af1158015610dec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1091906133ce565b905080610e515760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610538565b6001600160a01b0383165f9081526004602052604081206001018054849290610e7b90849061333c565b90915550506040518281526001600160a01b038416907f7e2c99819371db0a6fc6f4269fe872496e44f502df19ba3eae594b7a1598746090602001610ca3565b6003545f906001600160a01b0316331480610edf57505f546001600160a01b031633145b610efb5760405162461bcd60e51b8152600401610538906132e1565b6040805180820190915260048152636161766560e01b60209182015284519085012084907fe0a39fef8aa5887c76606e7a14a5db8dc6676191e4866b2a609a3aa003b1832914801590610f93575060408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528151908201207f2b05eae252b2d830081b9362c105fc1b4e5f974a0c53bee02c06419c2f4a117e14155b15610fb357806040516303622bc560e21b815260040161053891906133a5565b6040805180820190915260048152636161766560e01b6020918201528551908601207f1f5c6010755a7783899f9185eb5a247239989e6e1b7994d59f65c55ffc4e7cd7016110a9576001600160a01b0384165f908152600460205260409020600201548311156110655760405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e7420696e76657374656420616d6f756e74000000006044820152606401610538565b61106f8484611d5b565b6001600160a01b0385165f9081526004602052604081206002018054929450859290919061109e90849061333c565b9091555061119e9050565b60408051808201909152600881526718dbdb5c1bdd5b9960c21b6020918201528551908601207fd4fa151dad4d27cff7e46c9d3efa03e4b1a068b5f3ac411fd3f9be63d0b5ee820161119e576001600160a01b0384165f9081526004602052604090206003015483111561115f5760405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e7420696e76657374656420616d6f756e74000000006044820152606401610538565b6111698484611e48565b6001600160a01b0385165f9081526004602052604081206003018054929450859290919061119890849061333c565b90915550505b6001600160a01b0384165f90815260046020526040812060010180548492906111c890849061334f565b9091555050509392505050565b6111dd611ce0565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633148061122157505f546001600160a01b031633145b61123d5760405162461bcd60e51b8152600401610538906132e1565b6040805180820190915260078152660756e69737761760cc1b60209182015288519089012088907fa2a03459171c76bff45817330c10ef9f8af07011a33005b73b50189bbc7e7132148015906112d957506040805180820190915260098152686165726f64726f6d6560b81b6020918201528151908201207fc570e6c17f57bc6841b1057f94fcf1785f440006714dbd98f64d859b54cd25d314155b156112f957806040516303622bc560e21b815260040161053891906133a5565b6001600160a01b0388165f908152600460205260409020600101548611156113635760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e742062616c616e636520746f6b656e3000000000006044820152606401610538565b6001600160a01b0387165f908152600460205260409020600101548511156113cd5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e742062616c616e636520746f6b656e3100000000006044820152606401610538565b6040805180820190915260078152660756e69737761760cc1b6020918201528951908a01207f5d5fcba6e8e389400ba7e8ccf3ef1060750f8fee5ccffa48c4afe76443818ece0161148c5761142788888888888888611ff7565b506001600160a01b0388165f908152600460208190526040822001805488929061145290849061334f565b90915550506001600160a01b0387165f908152600460208190526040822001805487929061148190849061334f565b909155506114f29050565b6040805180820190915260098152686165726f64726f6d6560b81b6020918201528951908a01207f3a8f193e80a84397be4efa806b030e87a0bbfff98eb2426709b27a64ab32da2d016114f2576040516305fcd0f760e01b815260040160405180910390fd5b6001600160a01b0388165f908152600460205260408120600101805488929061151c90849061333c565b90915550506001600160a01b0387165f908152600460205260408120600101805487929061154b90849061333c565b9091555050505050505050505050565b6003546001600160a01b031633148061157d57505f546001600160a01b031633145b6115995760405162461bcd60e51b8152600401610538906132e1565b6040805180820190915260078152660756e69737761760cc1b60209182015284519085012084907fa2a03459171c76bff45817330c10ef9f8af07011a33005b73b50189bbc7e71321480159061163557506040805180820190915260098152686165726f64726f6d6560b81b6020918201528151908201207fc570e6c17f57bc6841b1057f94fcf1785f440006714dbd98f64d859b54cd25d314155b1561165557806040516303622bc560e21b815260040161053891906133a5565b6040805180820190915260078152660756e69737761760cc1b6020918201528551908601207f5d5fcba6e8e389400ba7e8ccf3ef1060750f8fee5ccffa48c4afe76443818ece016116b3576116ae8484610bb88561239a565b611719565b6040805180820190915260098152686165726f64726f6d6560b81b6020918201528551908601207f3a8f193e80a84397be4efa806b030e87a0bbfff98eb2426709b27a64ab32da2d01611719576040516305fcd0f760e01b815260040160405180910390fd5b5050505050565b6002546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015611766573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178a91906133b7565b905090565b611797611ce0565b6001600160a01b0381166117c057604051631e4fbdf760e01b81525f6004820152602401610538565b6117c981611d0c565b50565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018590525f919087169063095ea7b3906044016020604051808303815f875af115801561183b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185f91906133ce565b5060408051610100810182526001600160a01b0388811682528781166020830190815262ffffff8681168486019081523060608601908152426080870190815260a087018c815260c088018c81525f60e08a01908152995163414bf38960e01b815289518916600482015296518816602488015293519094166044860152905185166064850152516084840152905160a48301525160c48201529251811660e484015290917f00000000000000000000000000000000000000000000000000000000000000009091169063414bf38990610104016020604051808303815f875af115801561194f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197391906133b7565b604080516001600160a01b038a811682528981166020830152918101889052606081018390529193507f000000000000000000000000000000000000000000000000000000000000000016907fad56699d0f375866eb895ed27203058a36a713382aaded78eb6b67da266d43329060800160405180910390a25095945050505050565b60015460405163095ea7b360e01b81526001600160a01b039182166004820152602481018390525f9184169063095ea7b3906044016020604051808303815f875af1158015611a47573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a6b91906133ce565b905080611aca5760405162461bcd60e51b815260206004820152602760248201527f417070726f76616c206f6620617373657420696e746f204161766520706f6f6c6044820152660819985a5b195960ca1b6064820152608401610538565b60015460405163617ba03760e01b81526001600160a01b038581166004830152602482018590523060448301525f60648301529091169063617ba037906084015f604051808303815f87803b158015611b21575f80fd5b505af1158015611b33573d5f803e3d5ffd5b505050507f76bfb501e0568602c59c0cffcde817c5bc2696480830199d9f8c115afe02c54e8383604051611b689291906133e7565b60405180910390a1505050565b60025460405163095ea7b360e01b81526001600160a01b039182166004820152602481018390525f9184169063095ea7b3906044016020604051808303815f875af1158015611bc6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bea91906133ce565b905080611c485760405162461bcd60e51b815260206004820152602660248201527f417070726f76616c206f6620617373657420696e746f20436f6d706f756e642060448201526519985a5b195960d21b6064820152608401610538565b600254604051634232cd6360e01b81523060048201526001600160a01b0385811660248301526044820185905290911690634232cd63906064015f604051808303815f87803b158015611c99575f80fd5b505af1158015611cab573d5f803e3d5ffd5b505050507f76bfb501e0568602c59c0cffcde817c5bc2696480830199d9f8c115afe02c54e8383604051611b6892919061341b565b5f546001600160a01b03163314610ac75760405163118cdaa760e01b8152336004820152602401610538565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f80611d656103f4565b5050505050905082811015611d8c5760405162461bcd60e51b815260040161053890613453565b600154604051631a4ca37b60e21b81526001600160a01b03868116600483015260248201869052306044830152909116906369328dec906064016020604051808303815f875af1158015611de2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e0691906133b7565b91507ff2119ac293790f480d31afd7d613930c9e10d9432d0dedb82738f50368fa27b58484604051611e399291906133e7565b60405180910390a15092915050565b5f80611e52611720565b905082811015611e745760405162461bcd60e51b815260040161053890613453565b6040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015611eb8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611edc91906133b7565b60025460405163f3fef3a360e01b81526001600160a01b0388811660048301526024820188905292935091169063f3fef3a3906044015f604051808303815f87803b158015611f29575f80fd5b505af1158015611f3b573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f92506001600160a01b03881691506370a0823190602401602060405180830381865afa158015611f83573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa791906133b7565b9050611fb3828261333c565b93507ff2119ac293790f480d31afd7d613930c9e10d9432d0dedb82738f50368fa27b58685604051611fe692919061341b565b60405180910390a150505092915050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828a8a886040518463ffffffff1660e01b8152600401612049939291906130f8565b602060405180830381865afa158015612064573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120889190613120565b90506001600160a01b0381166120b05760405162461bcd60e51b81526004016105389061313b565b5f80896001600160a01b03168b6001600160a01b0316106120d257898b6120d5565b8a8a5b915091505f826001600160a01b03168c6001600160a01b0316146120f957886120fb565b895b90505f836001600160a01b03168d6001600160a01b03161461211d578a61211f565b895b60405163095ea7b360e01b81526001600160a01b038781166004830152602482018590529192509085169063095ea7b3906044016020604051808303815f875af115801561216f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061219391906133ce565b5060405163095ea7b360e01b81526001600160a01b0386811660048301526024820183905284169063095ea7b3906044016020604051808303815f875af11580156121e0573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061220491906133ce565b505f856001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015612242573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122669190613187565b50505050505090505f6122788a612679565b90505f6122848a612679565b90506122938383838888612ab4565b98505f80896001600160a01b0316633c8a7d8d308f8f8f306040516020016122ca91906001600160a01b0391909116815260200190565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016122f9959493929190613495565b60408051808303815f875af1158015612314573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061233891906134e1565b91509150896001600160a01b03167fce0669c03a6bebf1a7a80046c110092cafdff0bb527ff2e4ea213faf8f07cf118a8a8e868660405161237d959493929190613503565b60405180910390a250505050505050505050979650505050505050565b604051630b4c774160e11b81525f906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631698ee82906123ec908890889088906004016130f8565b602060405180830381865afa158015612407573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061242b9190613120565b90506001600160a01b0381166124535760405162461bcd60e51b81526004016105389061313b565b5f80856001600160a01b0316876001600160a01b031610612475578587612478565b86865b915091505f80846001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156124ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124de9190613187565b5050505050915091505f6064826124f59190613228565b90505f612503836064613253565b60405163a34123a760e01b8152600284810b600483015282900b60248201526001600160801b038a1660448201529091505f9081906001600160a01b038a169063a34123a79060640160408051808303815f875af1158015612567573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061258b91906134e1565b6040516309e3d67b60e31b8152306004820152600287810b602483015286900b60448201526001600160801b0380841660648301528216608482015291935091506001600160a01b038a1690634f1eb3d89060a40160408051808303815f875af11580156125fb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261f919061353d565b5050886001600160a01b03167ff0c5c8e0b584b9430fbe397d62831fc7eca3e734a39a08659847de97469501de89898d8686604051612662959493929190613503565b60405180910390a250505050505050505050505050565b5f620d89e719600283900b128015906126a4575061269a620d89e71961356e565b60020b8260020b13155b6126df5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964207469636b60a01b6044820152606401610538565b5f808360020b126126f3578260020b612700565b8260020b6127009061358e565b90505f816001165f0361271757600160801b612729565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612768576080612763826ffff97272373d413259a46990580e213a6135a8565b901c90505b600482161561279257608061278d826ffff2e50f5f656932ef12357cf3c7fdcc6135a8565b901c90505b60088216156127bc5760806127b7826fffe5caca7e10e4e61c3624eaa0941cd06135a8565b901c90505b60108216156127e65760806127e1826fffcb9843d60f6159c9db58835c9266446135a8565b901c90505b602082161561281057608061280b826fff973b41fa98c081472e6896dfb254c06135a8565b901c90505b604082161561283a576080612835826fff2ea16466c96a3843ec78b326b528616135a8565b901c90505b608082161561286457608061285f826ffe5dee046a99a2a811c461f1969c30536135a8565b901c90505b61010082161561288f57608061288a826ffcbe86c7900a88aedcffc83b479aa3a46135a8565b901c90505b6102008216156128ba5760806128b5826ff987a7253ac413176f2b074cf7815e546135a8565b901c90505b6104008216156128e55760806128e0826ff3392b0822b70005940c7a398e4b70f36135a8565b901c90505b61080082161561291057608061290b826fe7159475a2c29b7443b29c7fa6e889d96135a8565b901c90505b61100082161561293b576080612936826fd097f3bdfd2022b8845ad8f792aa58256135a8565b901c90505b612000821615612966576080612961826fa9f746462d870fdf8a65dc1f90e061e56135a8565b901c90505b61400082161561299157608061298c826f70d869a156d2a1b890bb3df62baf32f76135a8565b901c90505b6180008216156129bc5760806129b7826f31be135f97d08fd981231505542fcfa66135a8565b901c90505b620100008216156129e85760806129e3826f09aa508b5b7a84e1c677de54f3e99bc96135a8565b901c90505b62020000821615612a13576080612a0e826e5d6af8dedb81196699c329225ee6046135a8565b901c90505b62040000821615612a3d576080612a38826d2216e584f5fa1ea926041bedfe986135a8565b901c90505b62080000821615612a65576080612a60826b048a170391f7dc42444e8fa26135a8565b901c90505b5f8460020b1315612a7e57612a7b815f196135d3565b90505b612a8d640100000000826135e6565b15612a99576001612a9b565b5f5b612aac9060ff16602083901c61334f565b949350505050565b5f836001600160a01b0316856001600160a01b03161115612ad3579293925b846001600160a01b0316866001600160a01b031611612afe57612af7858585612b75565b9050612b6c565b836001600160a01b0316866001600160a01b03161015612b5e575f612b24878686612b75565b90505f612b32878986612be8565b9050806001600160801b0316826001600160801b031610612b535780612b55565b815b92505050612b6c565b612b69858584612be8565b90505b95945050505050565b5f826001600160a01b0316846001600160a01b03161115612b94579192915b5f612bb6856001600160a01b0316856001600160a01b0316600160601b612c1d565b9050612bdd612bd88483612bca89896135f9565b6001600160a01b0316612c1d565b612d8c565b9150505b9392505050565b5f826001600160a01b0316846001600160a01b03161115612c07579192915b612aac612bd883600160601b612bca88886135f9565b5f80805f19858709858702925082811083820303915050805f03612c51575f8411612c46575f80fd5b508290049050612be1565b808411612c5c575f80fd5b5f848688098084039381119092039190505f612c7a8619600161334f565b8616958690049593849004935f819003046001019050612c9a81846135a8565b909317925f612caa8760036135a8565b6002189050612cb981886135a8565b612cc490600261333c565b612cce90826135a8565b9050612cda81886135a8565b612ce590600261333c565b612cef90826135a8565b9050612cfb81886135a8565b612d0690600261333c565b612d1090826135a8565b9050612d1c81886135a8565b612d2790600261333c565b612d3190826135a8565b9050612d3d81886135a8565b612d4890600261333c565b612d5290826135a8565b9050612d5e81886135a8565b612d6990600261333c565b612d7390826135a8565b9050612d7f81866135a8565b9998505050505050505050565b806001600160801b0381168114612da1575f80fd5b919050565b6001600160a01b03811681146117c9575f80fd5b803562ffffff81168114612da1575f80fd5b5f805f60608486031215612dde575f80fd5b8335612de981612da6565b92506020840135612df981612da6565b9150612e0760408501612dba565b90509250925092565b5f805f8060808587031215612e23575f80fd5b8435612e2e81612da6565b93506020850135612e3e81612da6565b925060408501359150612e5360608601612dba565b905092959194509250565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112612e81575f80fd5b813567ffffffffffffffff80821115612e9c57612e9c612e5e565b604051601f8301601f19908116603f01168101908282118183101715612ec457612ec4612e5e565b81604052838152866020858801011115612edc575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f60608486031215612f0d575f80fd5b833567ffffffffffffffff811115612f23575f80fd5b612f2f86828701612e72565b9350506020840135612f4081612da6565b929592945050506040919091013590565b5f60208284031215612f61575f80fd5b8135612be181612da6565b5f8060408385031215612f7d575f80fd5b8235612f8881612da6565b946020939093013593505050565b8060020b81146117c9575f80fd5b5f805f805f805f80610100898b031215612fbc575f80fd5b883567ffffffffffffffff811115612fd2575f80fd5b612fde8b828c01612e72565b9850506020890135612fef81612da6565b96506040890135612fff81612da6565b9550606089013594506080890135935061301b60a08a01612dba565b925060c089013561302b81612f96565b915060e089013561303b81612f96565b809150509295985092959890939650565b5f805f806080858703121561305f575f80fd5b843567ffffffffffffffff811115613075575f80fd5b61308187828801612e72565b945050602085013561309281612da6565b925060408501356130a281612da6565b9396929550929360600135925050565b5f805f805f8060c087890312156130c7575f80fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b6001600160a01b03938416815291909216602082015262ffffff909116604082015260600190565b5f60208284031215613130575f80fd5b8151612be181612da6565b602080825260129082015271141bdbdb08191bd95cdb89dd08195e1a5cdd60721b604082015260600190565b805161ffff81168114612da1575f80fd5b80518015158114612da1575f80fd5b5f805f805f805f60e0888a03121561319d575f80fd5b87516131a881612da6565b60208901519097506131b981612f96565b95506131c760408901613167565b94506131d560608901613167565b93506131e360808901613167565b925060a088015160ff811681146131f8575f80fd5b915061320660c08901613178565b905092959891949750929550565b634e487b7160e01b5f52601160045260245ffd5b600282810b9082900b03627fffff198112627fffff8213171561324d5761324d613214565b92915050565b600281810b9083900b01627fffff8113627fffff198212171561324d5761324d613214565b80516001600160801b0381168114612da1575f80fd5b5f805f805f60a086880312156132a2575f80fd5b6132ab86613278565b945060208601519350604086015192506132c760608701613278565b91506132d560808701613278565b90509295509295909350565b60208082526013908201527227b7363c9030b3b2b73a1037b91037bbb732b960691b604082015260600190565b602080825260149082015273496e73756666696369656e742062616c616e636560601b604082015260600190565b8181038181111561324d5761324d613214565b8082018082111561324d5761324d613214565b5f81518084525f5b818110156133865760208185018101518683018201520161336a565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f612be16020830184613362565b5f602082840312156133c7575f80fd5b5051919050565b5f602082840312156133de575f80fd5b612be182613178565b6060808252600490820152634161766560e01b60808201526001600160a01b03929092166020830152604082015260a00190565b60608082526008908201526710dbdb5c1bdd5b9960c21b60808201526001600160a01b03929092166020830152604082015260a00190565b60208082526022908201527f43616e6e6f74207769746864726177206d6f7265207468616e20626f72726f77604082015261195960f21b606082015260800190565b60018060a01b03861681528460020b60208201528360020b60408201526001600160801b038316606082015260a060808201525f6134d660a0830184613362565b979650505050505050565b5f80604083850312156134f2575f80fd5b505080516020909101519092909150565b6001600160a01b0395861681529390941660208401526001600160801b039190911660408301526060820152608081019190915260a00190565b5f806040838503121561354e575f80fd5b61355783613278565b915061356560208401613278565b90509250929050565b5f8160020b627fffff19810361358657613586613214565b5f0392915050565b5f600160ff1b82016135a2576135a2613214565b505f0390565b808202811582820484141761324d5761324d613214565b634e487b7160e01b5f52601260045260245ffd5b5f826135e1576135e16135bf565b500490565b5f826135f4576135f46135bf565b500690565b6001600160a01b0382811682821603908082111561361957613619613214565b509291505056fea2646970667358221220fb5c2a00a8ae482dd197a7a109c3db4fe86b2f56f8b951d4b352b1a7ef8a30c264736f6c63430008160033a2646970667358221220472810b03add19bec8ad27296ac8d04aea1e9f33c3e4da127d25eb27ddda164d64736f6c63430008160033", + "nonce": "0x1ec", "chainId": "0x14a34" }, "additionalContracts": [], @@ -22,25 +22,25 @@ "receipts": [ { "status": "0x1", - "cumulativeGasUsed": "0x8078fc", + "cumulativeGasUsed": "0x97af31", "logs": [], "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "transactionHash": "0x4bcd3ea0a755da46d20fa618e7b7aa1bfb335bcb161203df48bb164193235b0d", - "transactionIndex": "0x21", - "blockHash": "0x64dc3ab57f4570a4126797625cf89d3af7a2333fe74b9180a8886dd72be1c543", - "blockNumber": "0x149d03a", - "gasUsed": "0x3aa811", - "effectiveGasPrice": "0xe15d4", - "from": "0x7e393441edc1bb1621318e000cdfc74947f23b26", + "transactionHash": "0x4f6a853d43237dcb7715e1e2e4a5dbf8c6483c200ea9d79eeacd6c3d54802ef4", + "transactionIndex": "0x33", + "blockHash": "0x081af5e84bb3796005fc2f4f01249b6262b696f53b2e9fecfe9f717fa8090e3a", + "blockNumber": "0x149eb1b", + "gasUsed": "0x3a1e42", + "effectiveGasPrice": "0xe5ce7", + "from": "0x12b2434a1022d5787bf06056f2885fe35de62bf8", "to": null, - "contractAddress": "0xba31d235cf7f92f857fe891b630110efe1e47002", + "contractAddress": "0x210088ae6ee018133791f20406bb239f1ea98379", "l1BaseFeeScalar": "0x44d", "l1BlobBaseFee": "0x1", "l1BlobBaseFeeScalar": "0xa118b", - "l1Fee": "0xf91ad7fe4b", - "l1GasPrice": "0x1b7591874", - "l1GasUsed": "0x202f9" + "l1Fee": "0x1a1084d7b8b", + "l1GasPrice": "0x2e0b84442", + "l1GasUsed": "0x20223" } ], "libraries": [], @@ -48,10 +48,10 @@ "returns": { "0": { "internal_type": "contract VaultFactory", - "value": "0xbA31d235cF7F92f857FE891B630110EFe1e47002" + "value": "0x210088AE6EE018133791f20406Bb239f1ea98379" } }, - "timestamp": 1738997609, + "timestamp": 1739011371, "chain": 84532, - "commit": "8832140" + "commit": "2319c6d" } \ No newline at end of file diff --git a/script/DeployVaultFactory.s.sol b/script/DeployVaultFactory.s.sol index 79b859c..e56d985 100644 --- a/script/DeployVaultFactory.s.sol +++ b/script/DeployVaultFactory.s.sol @@ -9,7 +9,6 @@ contract DeployVaultFactory is Script { uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); vm.startBroadcast(deployerPrivateKey); - // Deploy VaultFactory with the owner set to msg.sender VaultFactory vaultFactory = new VaultFactory(); vm.stopBroadcast(); diff --git a/src/Arbitrage.sol b/src/Arbitrage.sol index a89a6d1..6a9ff93 100644 --- a/src/Arbitrage.sol +++ b/src/Arbitrage.sol @@ -1,37 +1,31 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.22; +pragma solidity ^0.8.22; -// Import necessary interfaces for Balancer Vault, Flash Loans, and Uniswap V3 import "@balancer/balancer-v2-monorepo/pkg/interfaces/contracts/vault/IVault.sol"; import "@balancer/balancer-v2-monorepo/pkg/interfaces/contracts/vault/IFlashLoanRecipient.sol"; import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; -import {IQuoterV2} from "@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol"; /** * @title Arbitrage - * @author CentoAI + * @author Cento-AI * @notice Executes arbitrage opportunities between two Uniswap-like DEXs using Balancer V2 Flash Loans. + * @notice This contract is inherited by the Vault contract, and can be only used by the Vault contract. * @dev This contract borrows a flash loan, performs two consecutive swaps (e.g., DEX A → DEX B), - * repays the loan, and sends profits to the contract owner. - * Note: The current implementation does not account for Balancer's flash loan fees (see critical warning). + * repays the loan, and sends profits to the contract owner. + * @dev Note: The current implementation does not account for Balancer's flash loan fees (see critical warning). */ -contract Arbitrage is IFlashLoanRecipient { - /// @notice Balancer V2 Vault address (Ethereum mainnet) +contract ArbitrageContract is IFlashLoanRecipient { + /// @notice Balancer V2 Vault address (Base Sepolia) IVault private constant vault = IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); - /// @notice Owner address to receive arbitrage profits - address public owner; - /** * @dev Struct to encapsulate swap parameters for a single trade path. * @param routerPath Array with two elements: [firstSwapRouter, secondSwapRouter] - * @param quoterPath Placeholder for future quoter integration (unused in current code) * @param tokenPath Array with two elements: [tokenToBorrow, tokenToSwap] * @param fee Pool fee tier for Uniswap V3 swaps (e.g., 3000 = 0.3%) */ struct Trade { address[] routerPath; - address[] quoterPath; address[] tokenPath; uint24 fee; } @@ -45,39 +39,30 @@ contract Arbitrage is IFlashLoanRecipient { */ event TokensSwapped(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut); - /// @dev Sets the contract deployer as the owner - constructor() { - owner = msg.sender; - } + constructor() {} /** * @notice Initiates a flash loan for arbitrage execution - * @dev Can be called by any external address (profits go to owner) + * @dev Can only be called by the Vault contract * @param _routerPath [firstSwapRouter, secondSwapRouter] - Uniswap-compatible router addresses - * @param _quoterPath Placeholder parameter (unused in current implementation) * @param _tokenPath [tokenToBorrow, tokenToSwap] - Token addresses for the arbitrage path * @param _fee Uniswap V3 pool fee tier for swaps * @param _flashAmount Amount of tokenToBorrow to flash loan */ - function executeTrade( - address[] memory _routerPath, - address[] memory _quoterPath, - address[] memory _tokenPath, - uint24 _fee, - uint256 _flashAmount - ) external { - // Encode trade parameters for flash loan callback - bytes memory data = - abi.encode(Trade({routerPath: _routerPath, quoterPath: _quoterPath, tokenPath: _tokenPath, fee: _fee})); + function executeTrade(address[] memory _routerPath, address[] memory _tokenPath, uint24 _fee, uint256 _flashAmount) + internal + { + /// @dev Encode trade parameters for flash loan callback + bytes memory data = abi.encode(Trade({routerPath: _routerPath, tokenPath: _tokenPath, fee: _fee})); - // Configure flash loan parameters + /// @dev Configure flash loan parameters IERC20[] memory tokens = new IERC20[](1); tokens[0] = IERC20(_tokenPath[0]); // Token to borrow uint256[] memory amounts = new uint256[](1); amounts[0] = _flashAmount; // Loan amount - // Trigger Balancer flash loan + /// @dev Trigger Balancer flash loan vault.flashLoan(this, tokens, amounts, data); } @@ -97,39 +82,95 @@ contract Arbitrage is IFlashLoanRecipient { ) external override { require(msg.sender == address(vault), "Unauthorized: Only Balancer Vault"); - // Decode trade parameters from userData + /// @dev Decode trade parameters from userData Trade memory trade = abi.decode(userData, (Trade)); uint256 flashAmount = amounts[0]; - // First swap: Borrowed token → Intermediate token + /// @dev First swap: Borrowed token → Intermediate token _swapOnV3( - trade.routerPath[0], // First DEX router (e.g., Uniswap) - trade.tokenPath[0], // Borrowed token address - flashAmount, // Use entire flash loan amount - trade.tokenPath[1], // Token to receive - 0, // No minimum out (assuming optimistic arbitrage) - trade.fee // Pool fee tier + trade.routerPath[0], + /// @param routerPath[0] First DEX router (e.g., Uniswap) + trade.tokenPath[0], + /// @param tokenPath[0] Borrowed token address + flashAmount, + /// @param flashAmount Use entire flash loan amount + trade.tokenPath[1], + /// @param tokenPath[1] Token to receive + 0, + /// @param 0 No minimum out (assuming optimistic arbitrage) + trade.fee ); + /// @param fee Pool fee tier - // Second swap: Intermediate token → Borrowed token + /// @dev Second swap: Intermediate token → Borrowed token _swapOnV3( - trade.routerPath[1], // Second DEX router (e.g., Sushiswap) - trade.tokenPath[1], // Intermediate token - IERC20(trade.tokenPath[1]).balanceOf(address(this)), // Swap entire balance - trade.tokenPath[0], // Borrowed token (to repay loan) - flashAmount, // Minimum required to repay loan (slippage protection) - trade.fee // Pool fee tier + trade.routerPath[1], + /// @param routerPath[1] Second DEX router (e.g., Sushiswap) + trade.tokenPath[1], + /// @param tokenPath[1] Intermediate token + IERC20(trade.tokenPath[1]).balanceOf(address(this)), + /// @param IERC20(trade.tokenPath[1]).balanceOf(address(this)) Swap entire balance + trade.tokenPath[0], + /// @param trade.tokenPath[0] Borrowed token (to repay loan) + flashAmount, + /// @param flashAmount Minimum required to repay loan (slippage protection) + trade.fee ); + /// @param fee Pool fee tier - // Repay flash loan principal (WARNING: Missing fee repayment - see note) - IERC20(trade.tokenPath[0]).transfer(address(vault), flashAmount); - - // Transfer remaining balance (profits) to owner - uint256 profit = IERC20(trade.tokenPath[0]).balanceOf(address(this)); - IERC20(trade.tokenPath[0]).transfer(owner, profit); + /// @dev Repay flash loan principal (WARNING: Missing fee repayment - see note) + IERC20(trade.tokenPath[0]).transfer(address(this), flashAmount); } - // ========== INTERNAL FUNCTIONS ========== // + /** + * @notice Executes a single exact-input swap arbitrage on Uniswap V3 + * @dev This function is used to execute an arbitrage without a flash loan + * @dev Emits TokensSwapped event on success + * @param _routerPath [firstSwapRouter, secondSwapRouter] - Uniswap-compatible router addresses + * @param _tokenPath [tokenToBorrow, tokenToSwap] - Token addresses for the arbitrage path + * @param _fee Uniswap V3 pool fee tier for swaps + * @param _amount Amount of tokenToBorrow to swap + */ + function ArbitrageWithoutFlashLoan( + address[] memory _routerPath, + address[] memory _tokenPath, + uint24 _fee, + uint256 _amount + ) internal { + Trade memory trade = Trade({routerPath: _routerPath, tokenPath: _tokenPath, fee: _fee}); + + /// @dev First swap: Borrowed token → Intermediate token + _swapOnV3( + trade.routerPath[0], + /// @param routerPath[0] First DEX router (e.g., Uniswap) + trade.tokenPath[0], + /// @param tokenPath[0] Borrowed token address + _amount, + /// @param _amount Use entire flash loan amount + trade.tokenPath[1], + /// @param trade.tokenPath[1] Token to receive + 0, + /// @param 0 No minimum out (assuming optimistic arbitrage) + trade.fee + ); + /// @param fee Pool fee tier + + /// @dev Second swap: Intermediate token → Borrowed token + _swapOnV3( + trade.routerPath[1], + /// @param routerPath[1] Second DEX router (e.g., Sushiswap) + trade.tokenPath[1], + /// @param tokenPath[1] Intermediate token + IERC20(trade.tokenPath[1]).balanceOf(address(this)), + /// @param IERC20(trade.tokenPath[1]).balanceOf(address(this)) Swap entire balance + trade.tokenPath[0], + /// @param trade.tokenPath[0] Borrowed token (to repay loan) + _amount, + /// @param _amount Minimum required to repay loan (slippage protection) + trade.fee + ); + /// @param fee Pool fee tier + } /** * @notice Executes a single exact-input swap on Uniswap V3 @@ -149,24 +190,27 @@ contract Arbitrage is IFlashLoanRecipient { uint256 _amountOut, uint24 _fee ) internal { - // Approve router to spend input tokens + /// @dev Approve router to spend input tokens IERC20(_tokenIn).approve(_router, _amountIn); - // Configure single-hop swap parameters + /// @dev Configure single-hop swap parameters ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ tokenIn: _tokenIn, tokenOut: _tokenOut, fee: _fee, - recipient: address(this), // Send output tokens to this contract - deadline: block.timestamp, // Expire after current block + recipient: address(this), + /// @param recipient Send output tokens to this contract + deadline: block.timestamp, + /// @param deadline Expire after current block amountIn: _amountIn, - amountOutMinimum: _amountOut, // Minimum output for successful swap - sqrtPriceLimitX96: 0 // No price limit (accept any slippage) + amountOutMinimum: _amountOut, + /// @param amountOutMinimum Minimum output for successful swap + sqrtPriceLimitX96: 0 }); + /// @param sqrtPriceLimitX96 No price limit (accept any slippage) - // Execute swap on specified router + /// @dev Execute swap on specified router ISwapRouter(_router).exactInputSingle(params); - emit TokensSwapped(_tokenIn, _tokenOut, _amountIn, _amountOut); } } diff --git a/src/LiquidityManager.sol b/src/LiquidityManager.sol index de93d15..e201bd6 100644 --- a/src/LiquidityManager.sol +++ b/src/LiquidityManager.sol @@ -34,31 +34,17 @@ contract LiquidityManager { /// @notice Uniswap V3 events event TokensSwapped( - address indexed protocol, - address tokenIn, - address tokenOut, - uint256 amountIn, - uint256 amountOut + address indexed protocol, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut ); /// @notice For two token(uniswap) event LiquidityAdded( - address indexed pool, - address token0, - address token1, - uint128 liquidity, - uint256 amount0, - uint256 amount1 + address indexed pool, address token0, address token1, uint128 liquidity, uint256 amount0, uint256 amount1 ); /// @notice For two token(uniswap) event LiquidityRemoved( - address indexed pool, - address token0, - address token1, - uint128 liquidity, - uint256 amount0, - uint256 amount1 + address indexed pool, address token0, address token1, uint128 liquidity, uint256 amount0, uint256 amount1 ); /// @notice For single token(aave, compound) @@ -74,12 +60,7 @@ contract LiquidityManager { * @param _uniswapFactory Uniswap V3 factory address. * @dev Constructor to set the addresses of the Aave pool, Compound USDC, Uniswap router, Uniswap factory, and vault. */ - constructor( - address _aavePool, - address _compoundUsdc, - address _uniswapRouter, - address _uniswapFactory - ) { + constructor(address _aavePool, address _compoundUsdc, address _uniswapRouter, address _uniswapFactory) { aavePool = IPool(_aavePool); compoundUsdc = CometMainInterface(_compoundUsdc); uniswapRouter = ISwapRouter(_uniswapRouter); @@ -103,14 +84,8 @@ contract LiquidityManager { * @param _asset Asset to supply liquidity on. * @param _amount Amount of asset to supply. */ - function supplyLiquidityOnCompound( - address _asset, - uint256 _amount - ) internal { - bool approvedCompound = IERC20(_asset).approve( - address(compoundUsdc), - _amount - ); + function supplyLiquidityOnCompound(address _asset, uint256 _amount) internal { + bool approvedCompound = IERC20(_asset).approve(address(compoundUsdc), _amount); require(approvedCompound, "Approval of asset into Compound failed"); compoundUsdc.supplyTo(address(this), _asset, _amount); emit LiquiditySupplied("Compound", _asset, _amount); @@ -122,11 +97,8 @@ contract LiquidityManager { * @param _amount Amount of asset to withdraw. * @return amountWithdrawn Amount of asset withdrawn. */ - function withdrawLiquidityFromAave( - address _asset, - uint256 _amount - ) internal returns (uint256 amountWithdrawn) { - (uint256 collateral, , , , , ) = getAaveLiquidityStatus(); + function withdrawLiquidityFromAave(address _asset, uint256 _amount) internal returns (uint256 amountWithdrawn) { + (uint256 collateral,,,,,) = getAaveLiquidityStatus(); require(collateral >= _amount, "Cannot withdraw more than borrowed"); amountWithdrawn = aavePool.withdraw(_asset, _amount, address(this)); emit LiquidityWithdrawn("Aave", _asset, _amount); @@ -138,10 +110,10 @@ contract LiquidityManager { * @param _amount Amount of asset to withdraw. * @return amountWithdrawn Amount of asset withdrawn. */ - function withdrawLiquidityFromCompound( - address _asset, - uint256 _amount - ) internal returns (uint256 amountWithdrawn) { + function withdrawLiquidityFromCompound(address _asset, uint256 _amount) + internal + returns (uint256 amountWithdrawn) + { uint256 collateral = getCompoundLiquidityStatus(); require(collateral >= _amount, "Cannot withdraw more than borrowed"); uint256 collateralBefore = IERC20(_asset).balanceOf(address(this)); @@ -160,37 +132,27 @@ contract LiquidityManager { * @param fee fee tier for the swap. * @return amountOut amount of tokenOut received. */ - function swapOnUniswap( - address tokenIn, - address tokenOut, - uint256 amountIn, - uint256 amountOutMin, - uint24 fee - ) internal returns (uint256 amountOut) { + function swapOnUniswap(address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMin, uint24 fee) + internal + returns (uint256 amountOut) + { IERC20(tokenIn).approve(address(uniswapRouter), amountIn); /// @dev Execute swap. - ISwapRouter.ExactInputSingleParams memory params = ISwapRouter - .ExactInputSingleParams({ - tokenIn: tokenIn, - tokenOut: tokenOut, - fee: fee, - recipient: address(this), - /// @dev Output to vault - deadline: block.timestamp, - amountIn: amountIn, - amountOutMinimum: amountOutMin, - sqrtPriceLimitX96: 0 - }); + ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ + tokenIn: tokenIn, + tokenOut: tokenOut, + fee: fee, + recipient: address(this), + /// @dev Output to vault + deadline: block.timestamp, + amountIn: amountIn, + amountOutMinimum: amountOutMin, + sqrtPriceLimitX96: 0 + }); amountOut = uniswapRouter.exactInputSingle(params); - emit TokensSwapped( - address(uniswapRouter), - tokenIn, - tokenOut, - amountIn, - amountOut - ); + emit TokensSwapped(address(uniswapRouter), tokenIn, tokenOut, amountIn, amountOut); } /** @@ -217,9 +179,7 @@ contract LiquidityManager { require(pool != address(0), "Pool doesn't exist"); /// @dev Sort tokens. - (address token0, address token1) = tokenA < tokenB - ? (tokenA, tokenB) - : (tokenB, tokenA); + (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); /// @dev Transfer tokens from vault. uint256 amount0 = tokenA == token0 ? amountADesired : amountBDesired; @@ -230,39 +190,26 @@ contract LiquidityManager { IERC20(token1).approve(pool, amount1); /// @dev Get current pool price. - (uint160 sqrtPriceX96, , , , , , ) = IUniswapV3Pool(pool).slot0(); + (uint160 sqrtPriceX96,,,,,,) = IUniswapV3Pool(pool).slot0(); /// @dev Calculate liquidity using Uniswap libraries. uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower); uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper); - liquidity = LiquidityAmounts.getLiquidityForAmounts( - sqrtPriceX96, - sqrtRatioAX96, - sqrtRatioBX96, - amount0, - amount1 - ); + liquidity = + LiquidityAmounts.getLiquidityForAmounts(sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, amount0, amount1); /// @dev Add liquidity directly to pool. - (uint256 amount0Actual, uint256 amount1Actual) = IUniswapV3Pool(pool) - .mint( - address(this), - /// @dev Recipient (this contract) - tickLower, - tickUpper, - liquidity, - abi.encode(address(this)) - ); - /// @dev Callback data - - emit LiquidityAdded( - pool, - token0, - token1, + (uint256 amount0Actual, uint256 amount1Actual) = IUniswapV3Pool(pool).mint( + address(this), + /// @dev Recipient (this contract) + tickLower, + tickUpper, liquidity, - amount0Actual, - amount1Actual + abi.encode(address(this)) ); + /// @dev Callback data + + emit LiquidityAdded(pool, token0, token1, liquidity, amount0Actual, amount1Actual); } /** @@ -272,53 +219,30 @@ contract LiquidityManager { * @param _fee Pool fee tier * @param _liquidityToRemove Amount of liquidity to remove */ - function withdrawLiquidityFromUniswap( - address _tokenA, - address _tokenB, - uint24 _fee, - uint128 _liquidityToRemove - ) internal { + function withdrawLiquidityFromUniswap(address _tokenA, address _tokenB, uint24 _fee, uint128 _liquidityToRemove) + internal + { // Get pool address address pool = uniswapFactory.getPool(_tokenA, _tokenB, _fee); require(pool != address(0), "Pool doesn't exist"); // Sort tokens - (address token0, address token1) = _tokenA < _tokenB - ? (_tokenA, _tokenB) - : (_tokenB, _tokenA); + (address token0, address token1) = _tokenA < _tokenB ? (_tokenA, _tokenB) : (_tokenB, _tokenA); // Get current pool price and tick - (uint160 sqrtPriceX96, int24 tick, , , , , ) = IUniswapV3Pool(pool) - .slot0(); + (uint160 sqrtPriceX96, int24 tick,,,,,) = IUniswapV3Pool(pool).slot0(); // Determine tick range (you might want to adjust this based on your specific requirements) int24 tickLower = tick - 100; int24 tickUpper = tick + 100; // Burn liquidity - (uint256 amount0, uint256 amount1) = IUniswapV3Pool(pool).burn( - tickLower, - tickUpper, - _liquidityToRemove - ); + (uint256 amount0, uint256 amount1) = IUniswapV3Pool(pool).burn(tickLower, tickUpper, _liquidityToRemove); // Collect tokens to vault - IUniswapV3Pool(pool).collect( - address(this), - tickLower, - tickUpper, - uint128(amount0), - uint128(amount1) - ); + IUniswapV3Pool(pool).collect(address(this), tickLower, tickUpper, uint128(amount0), uint128(amount1)); - emit LiquidityRemoved( - pool, - token0, - token1, - _liquidityToRemove, - amount0, - amount1 - ); + emit LiquidityRemoved(pool, token0, token1, _liquidityToRemove, amount0, amount1); } /** @@ -349,11 +273,7 @@ contract LiquidityManager { * @notice Get the user's compound liquidity status. * @return balance The user's compound liquidity balance. */ - function getCompoundLiquidityStatus() - public - view - returns (uint256 balance) - { + function getCompoundLiquidityStatus() public view returns (uint256 balance) { balance = compoundUsdc.balanceOf(address(this)); } @@ -366,11 +286,7 @@ contract LiquidityManager { * @return amount0 Current amount of token0 in the position * @return amount1 Current amount of token1 in the position */ - function getUniswapLiquidityStatus( - address _tokenA, - address _tokenB, - uint24 _fee - ) + function getUniswapLiquidityStatus(address _tokenA, address _tokenB, uint24 _fee) public view returns (uint128 liquidity, uint256 amount0, uint256 amount1) @@ -380,22 +296,18 @@ contract LiquidityManager { require(pool != address(0), "Pool doesn't exist"); // Sort tokens - (address token0, address token1) = _tokenA < _tokenB - ? (_tokenA, _tokenB) - : (_tokenB, _tokenA); + (address token0, address token1) = _tokenA < _tokenB ? (_tokenA, _tokenB) : (_tokenB, _tokenA); // Get current pool price and tick - (uint160 sqrtPriceX96, int24 tick, , , , , ) = IUniswapV3Pool(pool) - .slot0(); + (uint160 sqrtPriceX96, int24 tick,,,,,) = IUniswapV3Pool(pool).slot0(); // Determine tick range (you might want to adjust this based on your specific requirements) int24 tickLower = tick - 100; int24 tickUpper = tick + 100; // Destructure only the first three values - (liquidity, amount0, amount1, , ) = IUniswapV3Pool(pool).positions( - keccak256(abi.encodePacked(address(this), tickLower, tickUpper)) - ); + (liquidity, amount0, amount1,,) = + IUniswapV3Pool(pool).positions(keccak256(abi.encodePacked(address(this), tickLower, tickUpper))); return (liquidity, amount0, amount1); } diff --git a/src/Vault.sol b/src/Vault.sol index 164ce47..68661fb 100644 --- a/src/Vault.sol +++ b/src/Vault.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.22; + import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./LiquidityManager.sol"; @@ -8,11 +9,12 @@ import "./LiquidityManager.sol"; * @title Vault * @author Cento-AI * @notice This contract is used to manage user balances for the Cento-AI protocol. - * @notice This contract calls the LiquidityManager contract to mazimize profits on the user's balances. + * @notice This contract calls the LiquidityManager contract and the ArbitrageContract contract to mazimize profits on the user's balances. * @dev It allows users to deposit and withdraw ERC20 tokens. * @dev It also allows users to get their balance of a specific token. */ contract Vault is Ownable, LiquidityManager { + /// @notice The agent address is the address that can call the liquidity functions. address public agent; struct UserBalance { @@ -33,14 +35,14 @@ contract Vault is Ownable, LiquidityManager { error AerodromeNotImplemented(); modifier onlyAgent() { - require(msg.sender == agent, "Only agent"); + require(msg.sender == agent || msg.sender == owner(), "Only agent or owner"); _; } modifier validLendingProtocol(string memory protocol) { if ( - keccak256(bytes(protocol)) != keccak256(bytes("aave")) && - keccak256(bytes(protocol)) != keccak256(bytes("compound")) + keccak256(bytes(protocol)) != keccak256(bytes("aave")) + && keccak256(bytes(protocol)) != keccak256(bytes("compound")) ) { revert InvalidProtocol(protocol); } @@ -49,14 +51,22 @@ contract Vault is Ownable, LiquidityManager { modifier validLPProtocol(string memory protocol) { if ( - keccak256(bytes(protocol)) != keccak256(bytes("uniswap")) && - keccak256(bytes(protocol)) != keccak256(bytes("aerodrome")) + keccak256(bytes(protocol)) != keccak256(bytes("uniswap")) + && keccak256(bytes(protocol)) != keccak256(bytes("aerodrome")) ) { revert InvalidProtocol(protocol); } _; } + /** + * @param _owner The owner of the contract. + * @param _agent The agent address. + * @param _aavePool The Aave pool address. + * @param _compoundUsdc The Compound USDC address. + * @param _uniswapRouter The Uniswap router address. + * @param _uniswapFactory The Uniswap factory address. + */ constructor( address _owner, address _agent, @@ -64,15 +74,7 @@ contract Vault is Ownable, LiquidityManager { address _compoundUsdc, address _uniswapRouter, address _uniswapFactory - ) - Ownable(_owner) - LiquidityManager( - _aavePool, - _compoundUsdc, - _uniswapRouter, - _uniswapFactory - ) - { + ) Ownable(_owner) LiquidityManager(_aavePool, _compoundUsdc, _uniswapRouter, _uniswapFactory) { agent = _agent; } @@ -82,15 +84,8 @@ contract Vault is Ownable, LiquidityManager { * @param _amount Amount of token to deposit. */ function depositERC20(address _token, uint256 _amount) external onlyOwner { - require( - IERC20(_token).allowance(msg.sender, address(this)) >= _amount, - "Insufficient allowance" - ); - bool success = IERC20(_token).transferFrom( - msg.sender, - address(this), - _amount - ); + require(IERC20(_token).allowance(msg.sender, address(this)) >= _amount, "Insufficient allowance"); + bool success = IERC20(_token).transferFrom(msg.sender, address(this), _amount); require(success, "Transfer failed"); tokenAddressToStruct[_token].balance += _amount; emit ERC20Deposited(_token, _amount); @@ -102,10 +97,7 @@ contract Vault is Ownable, LiquidityManager { * @param _amount Amount of token to withdraw. */ function withdrawERC20(address _token, uint256 _amount) external onlyOwner { - require( - tokenAddressToStruct[_token].balance >= _amount, - "Insufficient balance" - ); + require(tokenAddressToStruct[_token].balance >= _amount, "Insufficient balance"); IERC20(_token).approve(owner(), _amount); bool success = IERC20(_token).transfer(owner(), _amount); require(success, "Transfer failed"); @@ -121,15 +113,18 @@ contract Vault is Ownable, LiquidityManager { agent = _agent; } - function lendTokens( - string memory protocol, - address token, - uint256 amount - ) external onlyAgent validLendingProtocol(protocol) { - require( - tokenAddressToStruct[token].balance >= amount, - "Insufficient balance" - ); + /** + * @notice Lend single tokens to a lending protocol. + * @param protocol The protocol to lend to (aave or compound). + * @param token The token to lend. + * @param amount The amount of token to lend. + */ + function lendTokens(string memory protocol, address token, uint256 amount) + external + onlyAgent + validLendingProtocol(protocol) + { + require(tokenAddressToStruct[token].balance >= amount, "Insufficient balance"); if (keccak256(bytes(protocol)) == keccak256(bytes("aave"))) { supplyLiquidityOnAave(token, amount); @@ -142,28 +137,24 @@ contract Vault is Ownable, LiquidityManager { tokenAddressToStruct[token].balance -= amount; } - function withdrawLentTokens( - string memory protocol, - address token, - uint256 amount - ) + /** + * @notice Withdraw lent tokens from a lending protocol. + * @param protocol The protocol to withdraw from (aave or compound). + * @param token The token to withdraw. + * @param amount The amount of token to withdraw. + */ + function withdrawLentTokens(string memory protocol, address token, uint256 amount) external onlyAgent validLendingProtocol(protocol) returns (uint256 amountWithdrawn) { if (keccak256(bytes(protocol)) == keccak256(bytes("aave"))) { - require( - tokenAddressToStruct[token].investedInAave >= amount, - "Insufficient invested amount" - ); + require(tokenAddressToStruct[token].investedInAave >= amount, "Insufficient invested amount"); amountWithdrawn = withdrawLiquidityFromAave(token, amount); tokenAddressToStruct[token].investedInAave -= amount; } else if (keccak256(bytes(protocol)) == keccak256(bytes("compound"))) { - require( - tokenAddressToStruct[token].investedInCompound >= amount, - "Insufficient invested amount" - ); + require(tokenAddressToStruct[token].investedInCompound >= amount, "Insufficient invested amount"); amountWithdrawn = withdrawLiquidityFromCompound(token, amount); tokenAddressToStruct[token].investedInCompound -= amount; } @@ -172,7 +163,17 @@ contract Vault is Ownable, LiquidityManager { return amountWithdrawn; } - // TODO Add aerodrome + /** + * @notice Add liquidity to a LP protocol(two tokens). + * @param protocol The protocol to add liquidity to (uniswap or aerodrome). + * @param token0 The first token to add liquidity to. + * @param token1 The second token to add liquidity to. + * @param amount0 The amount of token0 to add liquidity to. + * @param amount1 The amount of token1 to add liquidity to. + * @param fee The fee to add liquidity to. + * @param tickLower The lower tick to add liquidity to. + * @param tickUpper The upper tick to add liquidity to. + */ function addLiquidity( string memory protocol, address token0, @@ -183,30 +184,14 @@ contract Vault is Ownable, LiquidityManager { int24 tickLower, int24 tickUpper ) external onlyAgent validLPProtocol(protocol) { - require( - tokenAddressToStruct[token0].balance >= amount0, - "Insufficient balance token0" - ); - require( - tokenAddressToStruct[token1].balance >= amount1, - "Insufficient balance token1" - ); + require(tokenAddressToStruct[token0].balance >= amount0, "Insufficient balance token0"); + require(tokenAddressToStruct[token1].balance >= amount1, "Insufficient balance token1"); if (keccak256(bytes(protocol)) == keccak256(bytes("uniswap"))) { - supplyLiquidityOnUniswap( - token0, - token1, - amount0, - amount1, - fee, - tickLower, - tickUpper - ); + supplyLiquidityOnUniswap(token0, token1, amount0, amount1, fee, tickLower, tickUpper); tokenAddressToStruct[token0].investedInUniswap += amount0; tokenAddressToStruct[token1].investedInUniswap += amount1; - } else if ( - keccak256(bytes(protocol)) == keccak256(bytes("aerodrome")) - ) { + } else if (keccak256(bytes(protocol)) == keccak256(bytes("aerodrome"))) { revert AerodromeNotImplemented(); } @@ -214,36 +199,44 @@ contract Vault is Ownable, LiquidityManager { tokenAddressToStruct[token1].balance -= amount1; } - function removeLiquidity( - string memory protocol, - address token0, - address token1, - uint256 liquidityAmount - ) external onlyAgent validLPProtocol(protocol) { + /** + * @notice Remove liquidity from a LP protocol(two tokens). + * @param protocol The protocol to remove liquidity from (uniswap or aerodrome). + * @param token0 The first token to remove liquidity from. + * @param token1 The second token to remove liquidity from. + * @param liquidityAmount The amount of liquidity to remove. + */ + function removeLiquidity(string memory protocol, address token0, address token1, uint256 liquidityAmount) + external + onlyAgent + validLPProtocol(protocol) + { if (keccak256(bytes(protocol)) == keccak256(bytes("uniswap"))) { withdrawLiquidityFromUniswap( token0, token1, - 3000, // default fee + 3000, + /// @param fee default fee uint128(liquidityAmount) ); - } else if ( - keccak256(bytes(protocol)) == keccak256(bytes("aerodrome")) - ) { + } else if (keccak256(bytes(protocol)) == keccak256(bytes("aerodrome"))) { revert AerodromeNotImplemented(); } } - function swapOnUniswap( - address _tokenIn, - address _tokenOut, - uint256 _amountIn, - uint24 _fee - ) external onlyAgent returns (uint256 amountOut) { - require( - tokenAddressToStruct[_tokenIn].balance >= _amountIn, - "Insufficient balance" - ); + /** + * @notice Swap tokens on Uniswap. + * @param _tokenIn The token to swap from. + * @param _tokenOut The token to swap to. + * @param _amountIn The amount of tokenIn to swap. + * @param _fee The fee to swap on. + */ + function swapOnUniswap(address _tokenIn, address _tokenOut, uint256 _amountIn, uint24 _fee) + external + onlyAgent + returns (uint256 amountOut) + { + require(tokenAddressToStruct[_tokenIn].balance >= _amountIn, "Insufficient balance"); amountOut = swapOnUniswap(_tokenIn, _tokenOut, _amountIn, 1, _fee); tokenAddressToStruct[_tokenIn].balance -= _amountIn; tokenAddressToStruct[_tokenOut].balance += amountOut; @@ -254,9 +247,7 @@ contract Vault is Ownable, LiquidityManager { * @param _token Token address to get the balance of. * @return balance Balance of the user for the token. */ - function getStruct( - address _token - ) external view returns (UserBalance memory) { + function getUserStruct(address _token) external view returns (UserBalance memory) { return tokenAddressToStruct[_token]; } } diff --git a/src/VaultFactory.sol b/src/VaultFactory.sol index a1c4c9c..7a3be9a 100644 --- a/src/VaultFactory.sol +++ b/src/VaultFactory.sol @@ -1,11 +1,14 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.22; + import "./Vault.sol"; import "../script/HelperConfig.s.sol"; contract VaultFactory is HelperConfig { mapping(address => address) public ownerToVaultAddress; + event VaultCreated(address indexed owner, address indexed vault); + HelperConfig.NetworkConfig public activeNetworkConfig; constructor() { diff --git a/test/forked-uint/ArbitrageTest.t.sol b/test/forked-uint/ArbitrageTest.t.sol new file mode 100644 index 0000000..d8f2c00 --- /dev/null +++ b/test/forked-uint/ArbitrageTest.t.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.22; + +import {Test, console} from "forge-std/Test.sol"; +import {StdUtils} from "forge-std/StdUtils.sol"; +import {Vault} from "../../src/Vault.sol"; +import {ArbitrageContract} from "../../src/Arbitrage.sol"; +import {HelperConfig} from "../../script/HelperConfig.s.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract ArbitrageTest is Test { + HelperConfig public helperConfig; + HelperConfig.NetworkConfig public networkConfig; + address owner = address(1); + address user = address(2); + ArbitrageContract public arbitrage; + uint256 fork; + string BASE_SEPOLIA_RPC_URL_2 = vm.envString("BASE_SEPOLIA_RPC_URL_2"); + + function setUp() public { + helperConfig = new HelperConfig(); + networkConfig = helperConfig.getBaseSepoliaConfig(); + fork = vm.createSelectFork(BASE_SEPOLIA_RPC_URL_2); + vm.startPrank(owner); + arbitrage = new ArbitrageContract(); + vm.stopPrank(); + deal(networkConfig.usdc, user, 100 * 1e6); + } + + // function testFakeArbitrage() public { + // vm.startPrank(user); + // IERC20(networkConfig.usdc).approve(address(arbitrage), 2 * 1e6); + // IERC20(networkConfig.usdc).transfer(address(arbitrage), 2 * 1e6); + + // // Create dynamic arrays + // address[] memory routers = new address[](2); + // routers[0] = networkConfig.uniswapRouter; + // routers[1] = networkConfig.uniswapRouter; + + // address[] memory tokens = new address[](2); + // tokens[0] = networkConfig.usdc; + // tokens[1] = networkConfig.weth; + + // arbitrage.fakeArbitrage(routers, tokens, 3000, 1 * 1e6); + // vm.stopPrank(); + // } +} diff --git a/test/forked-uint/LiquidityManagerTest.t.sol b/test/forked-uint/LiquidityManagerTest.t.sol index f7692f0..fde13bc 100644 --- a/test/forked-uint/LiquidityManagerTest.t.sol +++ b/test/forked-uint/LiquidityManagerTest.t.sol @@ -37,7 +37,7 @@ contract LiquidityManagerTest is Test { fork = vm.createSelectFork(BASE_SEPOLIA_RPC_URL_2); vm.startPrank(owner); vaultFactory = new VaultFactory(); - address _vault = vaultFactory.createVault(); + address _vault = vaultFactory.createVault(owner); vault = Vault(_vault); deal(networkConfig.usdc, owner, 100 * 1e6); IERC20(networkConfig.usdc).approve(address(vault), 100 * 1e6); @@ -197,41 +197,25 @@ contract LiquidityManagerTest is Test { function testSupplyUSDCOnAave() public { vm.startPrank(networkConfig.agent); vault.lendTokens("aave", networkConfig.usdc, 10 * 1e6); - (uint256 totalCollateralBase, , , , , ) = vault - .getAaveLiquidityStatus(); - Vault.UserBalance memory userBalance = vault.getStruct( - networkConfig.usdc - ); + (uint256 totalCollateralBase,,,,,) = vault.getAaveLiquidityStatus(); + Vault.UserBalance memory userBalance = vault.getUserStruct(networkConfig.usdc); assertEq(userBalance.investedInAave, 10 * 1e6); assertEq(userBalance.balance, 90 * 1e6); assertGt(totalCollateralBase, 0); - assertEq( - IERC20(networkConfig.aaveUsdc).balanceOf(address(vault)), - 10 * 1e6 - ); + assertEq(IERC20(networkConfig.aaveUsdc).balanceOf(address(vault)), 10 * 1e6); vm.stopPrank(); } function testWithdrawUSDCFromAave() public { vm.startPrank(networkConfig.agent); vault.lendTokens("aave", networkConfig.usdc, 10 * 1e6); - uint256 amountWithdrawn = vault.withdrawLentTokens( - "aave", - networkConfig.usdc, - 5 * 1e6 - ); + uint256 amountWithdrawn = vault.withdrawLentTokens("aave", networkConfig.usdc, 5 * 1e6); assertEq(amountWithdrawn, 5 * 1e6); - (uint256 totalCollateralBase, , , , , ) = vault - .getAaveLiquidityStatus(); + (uint256 totalCollateralBase,,,,,) = vault.getAaveLiquidityStatus(); assertGt(totalCollateralBase, 0); - Vault.UserBalance memory userBalance = vault.getStruct( - networkConfig.usdc - ); + Vault.UserBalance memory userBalance = vault.getUserStruct(networkConfig.usdc); assertEq(userBalance.balance, 95 * 1e6); - assertEq( - IERC20(networkConfig.usdc).balanceOf(address(vault)), - 95 * 1e6 - ); + assertEq(IERC20(networkConfig.usdc).balanceOf(address(vault)), 95 * 1e6); vm.stopPrank(); } @@ -239,9 +223,7 @@ contract LiquidityManagerTest is Test { vm.startPrank(networkConfig.agent); vault.lendTokens("compound", networkConfig.usdc, 10 * 1e6); assertGt(vault.getCompoundLiquidityStatus(), 0); - Vault.UserBalance memory userBalance = vault.getStruct( - networkConfig.usdc - ); + Vault.UserBalance memory userBalance = vault.getUserStruct(networkConfig.usdc); assertEq(userBalance.investedInCompound, 10 * 1e6); assertEq(userBalance.balance, 90 * 1e6); vm.stopPrank(); @@ -250,15 +232,9 @@ contract LiquidityManagerTest is Test { function testWithdrawUSDCFromCompound() public { vm.startPrank(networkConfig.agent); vault.lendTokens("compound", networkConfig.usdc, 10 * 1e6); - uint256 amountWithdrawn = vault.withdrawLentTokens( - "compound", - networkConfig.usdc, - 5 * 1e6 - ); + uint256 amountWithdrawn = vault.withdrawLentTokens("compound", networkConfig.usdc, 5 * 1e6); assertEq(amountWithdrawn, 5 * 1e6); - Vault.UserBalance memory userBalance = vault.getStruct( - networkConfig.usdc - ); + Vault.UserBalance memory userBalance = vault.getUserStruct(networkConfig.usdc); assertEq(userBalance.balance, 95 * 1e6); assertEq(userBalance.investedInCompound, 5 * 1e6); vm.stopPrank(); diff --git a/test/forked-uint/VaultTest.t.sol b/test/forked-uint/VaultTest.t.sol index 57b6372..047bb51 100644 --- a/test/forked-uint/VaultTest.t.sol +++ b/test/forked-uint/VaultTest.t.sol @@ -29,7 +29,7 @@ contract VaultTest is Test { function testCreateVault() public { vm.startPrank(user); - address _vault = vaultFactory.createVault(); + address _vault = vaultFactory.createVault(user); Vault vault = Vault(_vault); assertEq(vault.owner(), user); vm.stopPrank(); @@ -37,25 +37,20 @@ contract VaultTest is Test { function testDepositERC20() public { vm.startPrank(user); - address _vault = vaultFactory.createVault(); + address _vault = vaultFactory.createVault(user); Vault vault = Vault(_vault); IERC20(networkConfig.usdc).approve(address(vault), 100 * 1e6); vault.depositERC20(networkConfig.usdc, 100 * 1e6); assertEq(IERC20(networkConfig.usdc).balanceOf(user), 0); - assertEq( - IERC20(networkConfig.usdc).balanceOf(address(vault)), - 100 * 1e6 - ); - Vault.UserBalance memory userBalance = vault.getStruct( - networkConfig.usdc - ); + assertEq(IERC20(networkConfig.usdc).balanceOf(address(vault)), 100 * 1e6); + Vault.UserBalance memory userBalance = vault.getUserStruct(networkConfig.usdc); assertEq(userBalance.balance, 100 * 1e6); vm.stopPrank(); } function testWithdrawERC20() public { vm.startPrank(user); - address _vault = vaultFactory.createVault(); + address _vault = vaultFactory.createVault(user); Vault vault = Vault(_vault); IERC20(networkConfig.usdc).approve(address(vault), 100 * 1e6); vault.depositERC20(networkConfig.usdc, 100 * 1e6);