Address Contract Partially Verified
Address
0xb5087F95643A9a4069471A28d32C569D9bd57fE4
Balance
0 ETH
Nonce
181
Code Size
22781 bytes
Creator
0xBFbaa134...600D at tx 0x96d94cfa...46b759
Indexed Transactions
0
Contract Bytecode
22781 bytes
0x608060405260043610620001245760003560e01c8063a4a78f0c11620000b2578063c2e3140a116200007d578063d34879971162000060578063d348799714620003a2578063d59bd26314620003c7578063f3995c6714620003ec57600080fd5b8063c2e3140a1462000355578063c45a0155146200036c57600080fd5b8063a4a78f0c14620002a8578063ac9650d814620002bf578063b0e21e8a14620002e5578063b3165aaf146200030c57600080fd5b80634659a49411620000f35780634659a49414620002185780637071f0c4146200022f578063787dce3d14620002545780638da5cb5b146200027957600080fd5b8063056f6b2b14620001295780630b2b685e146200017857806313af4035146200019d578063227efac314620001c4575b600080fd5b3480156200013657600080fd5b506200014e62000148366004620035b8565b62000403565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200018557600080fd5b506200014e62000197366004620035b8565b62000455565b348015620001aa57600080fd5b50620001c2620001bc366004620035f1565b620005de565b005b348015620001d157600080fd5b50620001e9620001e3366004620035b8565b620006d5565b604080516fffffffffffffffffffffffffffffffff90941684526020840192909252908201526060016200016f565b620001c26200022936600462003621565b62000d37565b3480156200023c57600080fd5b50620001c26200024e366004620036d1565b62000df4565b3480156200026157600080fd5b50620001c2620002733660046200372e565b62000f8a565b3480156200028657600080fd5b506000546200014e9073ffffffffffffffffffffffffffffffffffffffff1681565b620001c2620002b936600462003621565b620010bc565b620002d6620002d036600462003748565b62001194565b6040516200016f919062003809565b348015620002f257600080fd5b50620002fd60015481565b6040519081526020016200016f565b620003236200031d3660046200388d565b62001321565b604080519485526fffffffffffffffffffffffffffffffff90931660208501529183015260608201526080016200016f565b620001c26200036636600462003621565b62001613565b3480156200037957600080fd5b506200014e7f0000000000000000000000001f98431c8ad98523631ae4a59f267346ea31f98481565b348015620003af57600080fd5b50620001c2620003c1366004620038a1565b620016c3565b348015620003d457600080fd5b50620001e9620003e636600462003926565b62001869565b620001c2620003fd36600462003621565b62001fa5565b600062000438826040516020016200041c9190620039a5565b6040516020818303038152906040528051906020012062002023565b9050803b60008190036200044f5750600092915050565b50919050565b600080826040516020016200046b9190620039a5565b6040516020818303038152906040528051906020012090506200053481604051806020016200049a90620035aa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620004df9030908890602001620039bb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526200051d9291602001620039e7565b604051602081830303815290604052600062002193565b9150620005456020840184620035f1565b73ffffffffffffffffffffffffffffffffffffffff16818373ffffffffffffffffffffffffffffffffffffffff167fa633a76553e9d8d77256f9284d85ae2eb5e5ef445d9e5686e3e6270e2e8fd4a8866020016020810190620005a9919062003a1a565b620005bb6060890160408a0162003a1a565b60408051600293840b81529190920b60208201520160405180910390a450919050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60015460009081908190620006ee6020860186620035f1565b73ffffffffffffffffffffffffffffffffffffffff1663a34123a76200071b604088016020890162003a1a565b6200072d6060890160408a0162003a1a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600292830b6004820152910b60248201526000604482015260640160408051808303816000875af115801562000793573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007b9919062003a3a565b506000905080620007ce6020880188620035f1565b73ffffffffffffffffffffffffffffffffffffffff1663514ea4bf30620007fc60408b0160208c0162003a1a565b6200080e60608c0160408d0162003a1a565b60405160609390931b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602084015260e891821b6034840152901b6037820152603a01604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016200088791815260200190565b60a060405180830381865afa158015620008a5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008cb919062003a80565b6fffffffffffffffffffffffffffffffff8083169a5081169850909550935060009250620009009150506020890189620035f1565b73ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156200094b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000971919062003af1565b505050505050905060006200099a89602001602081019062000994919062003a1a565b62002370565b90506000620009b46200099460608c0160408d0162003a1a565b90506000620009c78484848c8c620026f5565b9050620009d78484848462002828565b9099509750620009f19350505060208901905088620035f1565b73ffffffffffffffffffffffffffffffffffffffff16634f1eb3d83062000a1f60408b0160208c0162003a1a565b62000a3160608c0160408d0162003a1a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff9093166004840152600291820b6024840152900b60448201526fffffffffffffffffffffffffffffffff80891660648301528716608482015260a40160408051808303816000875af115801562000acd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000af3919062003b96565b6fffffffffffffffffffffffffffffffff9182169650169350821562000c0e576000670de0b6b3a764000062000b2a858862003bfd565b62000b36919062003c6c565b90506000670de0b6b3a764000062000b4f868862003bfd565b62000b5b919062003c6c565b905062000bc56040518060e001604052808b80360381019062000b7f919062003cd7565b81523060208201819052604082015260600162000b9d858b62003d53565b815260200162000bae848a62003d53565b81526020016000815260200160008152506200291f565b6040805186815260208101869052939b5091995097507f8ff06abbd47998d6c3049811caffedad7aecc341ef315e29f40b58f7a673ee02910160405180910390a1505062000c93565b62000c8b6040518060e001604052808980360381019062000c30919062003cd7565b81526020013073ffffffffffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681526020018781526020018681526020016000815260200160008152506200291f565b919750955093505b8660405160200162000ca69190620039a5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206fffffffffffffffffffffffffffffffff8a1684529083018890529082018690529033907fe8a0353df51d0f27feccd54ad6bb3dec20a5c6666ef44c3146550e1e54ba6a389060600160405180910390a35050509193909250565b6040517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101869052606481018590526001608482015260ff841660a482015260c4810183905260e4810182905273ffffffffffffffffffffffffffffffffffffffff871690638fcbaf0c90610104015b600060405180830381600087803b15801562000dd357600080fd5b505af115801562000de8573d6000803e3d6000fd5b50505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016200065c565b8160005b8181101562000f835762000f7a85858381811062000e9d5762000e9d62003d6d565b905060200201602081019062000eb49190620035f1565b8487878581811062000eca5762000eca62003d6d565b905060200201602081019062000ee19190620035f1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff91909116906370a0823190602401602060405180830381865afa15801562000f4e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f74919062003d9c565b62002d8a565b60010162000e7b565b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146200100d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016200065c565b6706f05b59d3b2000081111562001081576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4d4158000000000000000000000000000000000000000000000000000000000060448201526064016200065c565b60018190556040518181527fdc0410a296e1e33943a772020d333d5f99319d7fcad932a484c53889f7aaa2b19060200160405180910390a150565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9073ffffffffffffffffffffffffffffffffffffffff88169063dd62ed3e90604401602060405180830381865afa1580156200114f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001175919062003d9c565b10156200118c576200118c86868686868662000d37565b505050505050565b60608167ffffffffffffffff811115620011b257620011b262003ca8565b604051908082528060200260200182016040528015620011e757816020015b6060815260200190600190039081620011d15790505b50905060005b828110156200131a57600080308686858181106200120f576200120f62003d6d565b905060200281019062001223919062003db6565b6040516200123392919062003e1e565b600060405180830381855af49150503d806000811462001270576040519150601f19603f3d011682016040523d82523d6000602084013e62001275565b606091505b509150915081620012e1576044815110156200129057600080fd5b60048101905080806020019051810190620012ac919062003e2e565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200065c919062003f05565b80848481518110620012f757620012f762003d6d565b602002602001018190525050508080620013119062003f1a565b915050620011ed565b5092915050565b6000806000808460e001358042111562001398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4f4c44000000000000000000000000000000000000000000000000000000000060448201526064016200065c565b6000620013a96020880188620035f1565b73ffffffffffffffffffffffffffffffffffffffff1663514ea4bf30620013d760408b0160208c0162003a1a565b620013e960608c0160408d0162003a1a565b60405160609390931b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602084015260e891821b6034840152901b6037820152603a01604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016200146291815260200190565b60a060405180830381865afa15801562001480573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620014a6919062003a80565b5050505090506200150c6040518060e0016040528089600001803603810190620014d1919062003cd7565b815230602082015233604082015260608a810135908201526080808b01359082015260a0808b01359082015260c0808b01359101526200291f565b9196509450925062001534876200152c61012082016101008301620035f1565b878462002e4b565b6040519096506200154a908890602001620039a5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101206200159461012089016101008a01620035f1565b604080516fffffffffffffffffffffffffffffffff89168152602081018890529081018690526060810189905273ffffffffffffffffffffffffffffffffffffffff919091169033907f099ba907192cf75889cdbe240a39ddfa9864b9c07b762c5a7ceab21056582ea69060800160405180910390a450509193509193565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152859073ffffffffffffffffffffffffffffffffffffffff88169063dd62ed3e90604401602060405180830381865afa15801562001686573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016ac919062003d9c565b10156200118c576200118c86868686868662001fa5565b6000620016d38284018462003f67565b8051602082015160408084015190517f1698ee8200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015262ffffff1660448201529192506000917f0000000000000000000000001f98431c8ad98523631ae4a59f267346ea31f98490911690631698ee8290606401602060405180830381865afa15801562001786573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620017ac919062003ff8565b90503373ffffffffffffffffffffffffffffffffffffffff8216146200182f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f57484f000000000000000000000000000000000000000000000000000000000060448201526064016200065c565b85156200184c576200184c8260000151836060015133896200311a565b84156200118c576200118c8260200151836060015133886200311a565b60008060008360e0013580421115620018df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4f4c44000000000000000000000000000000000000000000000000000000000060448201526064016200065c565b6000620018ec8662000403565b905073ffffffffffffffffffffffffffffffffffffffff81166200196f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200065c9060208082526004908201527f5748415400000000000000000000000000000000000000000000000000000000604082015260600190565b60008173ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620019bd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019e3919062003d9c565b90506000620019f66020890189620035f1565b73ffffffffffffffffffffffffffffffffffffffff1663514ea4bf3062001a2460408c0160208d0162003a1a565b62001a3660608d0160408e0162003a1a565b60405160609390931b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602084015260e891821b6034840152901b6037820152603a01604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040162001aaf91815260200190565b60a060405180830381865afa15801562001acd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001af3919062003a80565b505050509050600088608001351162001b69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f300000000000000000000000000000000000000000000000000000000000000060448201526064016200065c565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526080890135602482015273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b15801562001bdb57600080fd5b505af115801562001bf0573d6000803e3d6000fd5b5050505062001c17816fffffffffffffffffffffffffffffffff1689608001358462003185565b965062001c286020890189620035f1565b73ffffffffffffffffffffffffffffffffffffffff1663a34123a762001c5560408b0160208c0162003a1a565b62001c6760608c0160408d0162003a1a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600292830b6004820152910b60248201526fffffffffffffffffffffffffffffffff8a16604482015260640160408051808303816000875af115801562001cde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001d04919062003a3a565b909650945062001d186020890189620035f1565b73ffffffffffffffffffffffffffffffffffffffff16634f1eb3d862001d4560808b0160608c01620035f1565b62001d5760408c0160208d0162003a1a565b62001d6960608d0160408e0162003a1a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff9093166004840152600291820b6024840152900b60448201526fffffffffffffffffffffffffffffffff808a1660648301528816608482015260a40160408051808303816000875af115801562001e05573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e2b919062003b96565b6fffffffffffffffffffffffffffffffff918216975016945060a0880135861080159062001e5d57508760c001358510155b62001ec7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200065c9060208082526004908201527f534c495000000000000000000000000000000000000000000000000000000000604082015260600190565b60405162001eda908990602001620039a5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012062001f2260808a0160608b01620035f1565b604080516fffffffffffffffffffffffffffffffff8b168152602081018a90529081018890526080808c0135606083015273ffffffffffffffffffffffffffffffffffffffff929092169133917f39178cca1c18f66c7fcb2662a25ce89c78e21b6388eaff977a30b95a00ecf11d910160405180910390a4505050509193909250565b6040517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018690526064810185905260ff8416608482015260a4810183905260c4810182905273ffffffffffffffffffffffffffffffffffffffff87169063d505accf9060e40162000db8565b604080518082018252601081527f67363d3d37363d34f03d5260086018f30000000000000000000000000000000060209182015290517fff00000000000000000000000000000000000000000000000000000000000000918101919091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b166021820152603581018290527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6055820152600090819062002100906075015b6040516020818303038152906040528051906020012090565b6040517fd69400000000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b1660228201527f010000000000000000000000000000000000000000000000000000000000000060368201529091506200218c90603701620020e7565b9392505050565b6000806040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000858251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff81166200225b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4445504c4f594d454e545f4641494c454400000000000000000000000000000060448201526064016200065c565b620022668662002023565b925060008173ffffffffffffffffffffffffffffffffffffffff16858760405162002292919062004018565b60006040518083038185875af1925050503d8060008114620022d1576040519150601f19603f3d011682016040523d82523d6000602084013e620022d6565b606091505b50509050808015620022fe575073ffffffffffffffffffffffffffffffffffffffff84163b15155b62002366576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f494e495449414c495a4154494f4e5f4641494c4544000000000000000000000060448201526064016200065c565b5050509392505050565b60008060008360020b1262002389578260020b62002391565b8260020b6000035b9050620d89e8811115620023d1576040517f2bc80f3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600116600003620023f75770010000000000000000000000000000000062002409565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156200243e576ffff97272373d413259a46990580e213a0260801c5b60048216156200245e576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156200247e576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b60108216156200249e576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615620024be576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615620024de576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615620024fe576ffe5dee046a99a2a811c461f1969c30530260801c5b6101008216156200251f576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b61020082161562002540576ff987a7253ac413176f2b074cf7815e540260801c5b61040082161562002561576ff3392b0822b70005940c7a398e4b70f30260801c5b61080082161562002582576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615620025a3576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615620025c4576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615620025e5576f70d869a156d2a1b890bb3df62baf32f70260801c5b61800082161562002606576f31be135f97d08fd981231505542fcfa60260801c5b6201000082161562002628576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161562002649576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161562002669576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161562002687576b048a170391f7dc42444e8fa20260801c5b60008460020b1315620026ca57807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81620026c657620026c662003c3d565b0490505b640100000000810615620026e0576001620026e3565b60005b60ff16602082901c0192505050919050565b60008373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16111562002730579293925b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161162002779576200277185858562003259565b90506200281f565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1610156200280f576000620027bd87868662003259565b90506000620027ce8789866200330d565b9050806fffffffffffffffffffffffffffffffff16826fffffffffffffffffffffffffffffffff161062002803578062002805565b815b925050506200281f565b6200281c8585846200330d565b90505b95945050505050565b6000808373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16111562002864579293925b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1611620028ad57620028a585858562003386565b915062002916565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1610156200290657620028ef86858562003386565b9150620028fe85878562003445565b905062002916565b6200291385858562003445565b90505b94509492505050565b6000806000836060015160001480156200293b57506080840151155b15620029505750600091508190508062002d83565b600084600001516000015173ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015620029a6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620029cc919062003af1565b50505050505090506000620029e986600001516020015162002370565b9050600062002a0087600001516040015162002370565b905062002a198383838a606001518b60800151620026f5565b955050505083600001516000015173ffffffffffffffffffffffffffffffffffffffff16633c8a7d8d85602001518660000151602001518760000151604001518760405180608001604052808b600001516000015173ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002ab9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002adf919062003ff8565b73ffffffffffffffffffffffffffffffffffffffff1681526020018b600001516000015173ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002b4e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002b74919062003ff8565b73ffffffffffffffffffffffffffffffffffffffff1681526020018b600001516000015173ffffffffffffffffffffffffffffffffffffffff1663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002be3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002c09919062004036565b62ffffff1681526040808d015173ffffffffffffffffffffffffffffffffffffffff166020928301525162002c85929101815173ffffffffffffffffffffffffffffffffffffffff908116825260208084015182169083015260408084015162ffffff1690830152606092830151169181019190915260800190565b6040516020818303038152906040526040518663ffffffff1660e01b815260040162002cb695949392919062004056565b60408051808303816000875af115801562002cd5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002cfb919062003a3a565b60a08601519193509150821080159062002d1957508360c001518110155b62002d83576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200065c9060208082526004908201527f534c495000000000000000000000000000000000000000000000000000000000604082015260600190565b9193909250565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508062002e45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016200065c565b50505050565b60008062002e598662000403565b905073ffffffffffffffffffffffffffffffffffffffff811662002edc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200065c9060208082526004908201527f5748415400000000000000000000000000000000000000000000000000000000604082015260600190565b60008173ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002f2a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002f50919062003d9c565b90508060000362002fe757846fffffffffffffffffffffffffffffffff169250633b9aca00831162002fe1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200065c9060208082526004908201527f534d4f4c00000000000000000000000000000000000000000000000000000000604082015260600190565b62003086565b6200301881866fffffffffffffffffffffffffffffffff16866fffffffffffffffffffffffffffffffff1662003185565b92508260000362003086576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f300000000000000000000000000000000000000000000000000000000000000060448201526064016200065c565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018590528316906340c10f1990604401600060405180830381600087803b158015620030f757600080fd5b505af11580156200310c573d6000803e3d6000fd5b505050505050949350505050565b3073ffffffffffffffffffffffffffffffffffffffff84160362003161576200315b73ffffffffffffffffffffffffffffffffffffffff8516838362002d8a565b62002e45565b62002e4573ffffffffffffffffffffffffffffffffffffffff8516848484620034c4565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870985870292508281108382030391505080600003620031df5760008411620031d357600080fd5b5082900490506200218c565b808411620031ec57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b60008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16111562003294579192915b6000620032dc8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000062003185565b90506200281f62003307848388880373ffffffffffffffffffffffffffffffffffffffff1662003185565b62003585565b60008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16111562003348579192915b6200337e62003307836c0100000000000000000000000087870373ffffffffffffffffffffffffffffffffffffffff1662003185565b949350505050565b60008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161115620033c1579192915b8373ffffffffffffffffffffffffffffffffffffffff166200342c606060ff16846fffffffffffffffffffffffffffffffff16901b86860373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1662003185565b816200343c576200343c62003c3d565b04949350505050565b60008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16111562003480579192915b6200337e826fffffffffffffffffffffffffffffffff1685850373ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000062003185565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d116001600051141617169150508062000f83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064016200065c565b806fffffffffffffffffffffffffffffffff81168114620035a557600080fd5b919050565b61181680620040b283390190565b6000606082840312156200044f57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620035ee57600080fd5b50565b6000602082840312156200360457600080fd5b81356200218c81620035cb565b60ff81168114620035ee57600080fd5b60008060008060008060c087890312156200363b57600080fd5b86356200364881620035cb565b955060208701359450604087013593506060870135620036688162003611565b9598949750929560808101359460a0909101359350915050565b60008083601f8401126200369557600080fd5b50813567ffffffffffffffff811115620036ae57600080fd5b6020830191508360208260051b8501011115620036ca57600080fd5b9250929050565b600080600060408486031215620036e757600080fd5b833567ffffffffffffffff811115620036ff57600080fd5b6200370d8682870162003682565b90945092505060208401356200372381620035cb565b809150509250925092565b6000602082840312156200374157600080fd5b5035919050565b600080602083850312156200375c57600080fd5b823567ffffffffffffffff8111156200377457600080fd5b620037828582860162003682565b90969095509350505050565b60005b83811015620037ab57818101518382015260200162003791565b8381111562002e455750506000910152565b60008151808452620037d78160208601602086016200378e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562003880577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200386d858351620037bd565b9450928501929085019060010162003830565b5092979650505050505050565b600061012082840312156200044f57600080fd5b60008060008060608587031215620038b857600080fd5b8435935060208501359250604085013567ffffffffffffffff80821115620038df57600080fd5b818701915087601f830112620038f457600080fd5b8135818111156200390457600080fd5b8860208285010111156200391757600080fd5b95989497505060200194505050565b600061010082840312156200044f57600080fd5b8060020b8114620035ee57600080fd5b80356200395781620035cb565b73ffffffffffffffffffffffffffffffffffffffff16825260208101356200397f816200393a565b60020b6020830152604081013562003997816200393a565b8060020b6040840152505050565b60608101620039b582846200394a565b92915050565b73ffffffffffffffffffffffffffffffffffffffff83168152608081016200218c60208301846200394a565b60008351620039fb8184602088016200378e565b83519083019062003a118183602088016200378e565b01949350505050565b60006020828403121562003a2d57600080fd5b81356200218c816200393a565b6000806040838503121562003a4e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff81168114620035a557600080fd5b600080600080600060a0868803121562003a9957600080fd5b62003aa48662003a5f565b9450602086015193506040860151925062003ac26060870162003a5f565b915062003ad26080870162003a5f565b90509295509295909350565b805161ffff81168114620035a557600080fd5b600080600080600080600060e0888a03121562003b0d57600080fd5b875162003b1a81620035cb565b602089015190975062003b2d816200393a565b955062003b3d6040890162003ade565b945062003b4d6060890162003ade565b935062003b5d6080890162003ade565b925060a088015162003b6f8162003611565b60c0890151909250801515811462003b8657600080fd5b8091505092959891949750929550565b6000806040838503121562003baa57600080fd5b62003bb58362003a5f565b915062003bc56020840162003a5f565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562003c385762003c3862003bce565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008262003ca3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006060828403121562003cea57600080fd5b6040516060810181811067ffffffffffffffff8211171562003d105762003d1062003ca8565b604052823562003d2081620035cb565b8152602083013562003d32816200393a565b6020820152604083013562003d47816200393a565b60408201529392505050565b60008282101562003d685762003d6862003bce565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121562003daf57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811262003dec57600080fd5b83018035915067ffffffffffffffff82111562003e0857600080fd5b602001915036819003821315620036ca57600080fd5b8183823760009101908152919050565b60006020828403121562003e4157600080fd5b815167ffffffffffffffff8082111562003e5a57600080fd5b818401915084601f83011262003e6f57600080fd5b81518181111562003e845762003e8462003ca8565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171562003ecd5762003ecd62003ca8565b8160405282815287602084870101111562003ee757600080fd5b62003efa8360208301602088016200378e565b979650505050505050565b6020815260006200218c6020830184620037bd565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003f4e5762003f4e62003bce565b5060010190565b62ffffff81168114620035ee57600080fd5b60006080828403121562003f7a57600080fd5b6040516080810181811067ffffffffffffffff8211171562003fa05762003fa062003ca8565b604052823562003fb081620035cb565b8152602083013562003fc281620035cb565b6020820152604083013562003fd78162003f55565b6040820152606083013562003fec81620035cb565b60608201529392505050565b6000602082840312156200400b57600080fd5b81516200218c81620035cb565b600082516200402c8184602087016200378e565b9190910192915050565b6000602082840312156200404957600080fd5b81516200218c8162003f55565b73ffffffffffffffffffffffffffffffffffffffff861681528460020b60208201528360020b60408201526fffffffffffffffffffffffffffffffff8316606082015260a06080820152600062003efa60a0830184620037bd56fe6101606040523480156200001257600080fd5b506040516200181638038062001816833981016040819052620000359162000367565b80600001516001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000078573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009e91906200040a565b6001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620000dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000106919081019062000464565b81600001516001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000149573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016f91906200040a565b6001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001ad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001d7919081019062000464565b604051602001620001ea9291906200051c565b60408051601f198184030181528282019091526008825267042554e4e492d4c560c41b602083015290601260006200022384826200060d565b5060016200023283826200060d565b5060ff81166080524660a0526200024862000284565b60c052505081516001600160a01b0390811660e0526020830151600290810b6101005260409093015190920b6101205250166101405262000757565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051620002b89190620006d9565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6001600160a01b03811681146200033657600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051600281900b81146200036257600080fd5b919050565b60008082840360808112156200037c57600080fd5b8351620003898162000320565b92506060601f19820112156200039e57600080fd5b50604051606081016001600160401b0381118282101715620003c457620003c462000339565b6040526020840151620003d78162000320565b8152620003e7604085016200034f565b6020820152620003fa606085016200034f565b6040820152809150509250929050565b6000602082840312156200041d57600080fd5b81516200042a8162000320565b9392505050565b60005b838110156200044e57818101518382015260200162000434565b838111156200045e576000848401525b50505050565b6000602082840312156200047757600080fd5b81516001600160401b03808211156200048f57600080fd5b818401915084601f830112620004a457600080fd5b815181811115620004b957620004b962000339565b604051601f8201601f19908116603f01168101908382118183101715620004e457620004e462000339565b81604052828152876020848701011115620004fe57600080fd5b6200051183602083016020880162000431565b979650505050505050565b650213ab73734960d51b8152600083516200053f81600685016020880162000431565b602f60f81b60069184019182015283516200056281600784016020880162000431565b620204c560ec1b60079290910191820152600a01949350505050565b600181811c908216806200059357607f821691505b602082108103620005b457634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200060857600081815260208120601f850160051c81016020861015620005e35750805b601f850160051c820191505b818110156200060457828155600101620005ef565b5050505b505050565b81516001600160401b0381111562000629576200062962000339565b62000641816200063a84546200057e565b84620005ba565b602080601f831160018114620006795760008415620006605750858301515b600019600386901b1c1916600185901b17855562000604565b600085815260208120601f198616915b82811015620006aa5788860151825594840194600190910190840162000689565b5085821015620006c95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000808354620006e9816200057e565b600182811680156200070457600181146200071a576200074b565b60ff19841687528215158302870194506200074b565b8760005260208060002060005b85811015620007425781548a82015290840190820162000727565b50505082870194505b50929695505050505050565b60805160a05160c05160e051610100516101205161014051611056620007c0600039600081816102380152818161063a01526106f901526000610274015260006102ae0152600061018101526000610600015260006105cb015260006101f701526110566000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806355b812a8116100b257806395d89b4111610081578063a9059cbb11610066578063a9059cbb1461032b578063d505accf1461033e578063dd62ed3e1461035157600080fd5b806395d89b41146103105780639dc29fac1461031857600080fd5b806355b812a81461026f57806359c4f905146102a957806370a08231146102d05780637ecebe00146102f057600080fd5b806323b872dd116101095780633644e515116100ee5780633644e5151461022b578063365a86fc1461023357806340c10f191461025a57600080fd5b806323b872dd146101df578063313ce567146101f257600080fd5b806306fdde031461013b578063095ea7b31461015957806316f0115b1461017c57806318160ddd146101c8575b600080fd5b61014361037c565b6040516101509190610ccf565b60405180910390f35b61016c610167366004610d6b565b61040a565b6040519015158152602001610150565b6101a37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610150565b6101d160025481565b604051908152602001610150565b61016c6101ed366004610d95565b610483565b6102197f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610150565b6101d16105c7565b6101a37f000000000000000000000000000000000000000000000000000000000000000081565b61026d610268366004610d6b565b610622565b005b6102967f000000000000000000000000000000000000000000000000000000000000000081565b60405160029190910b8152602001610150565b6102967f000000000000000000000000000000000000000000000000000000000000000081565b6101d16102de366004610dd1565b60036020526000908152604090205481565b6101d16102fe366004610dd1565b60056020526000908152604090205481565b6101436106d4565b61026d610326366004610d6b565b6106e1565b61016c610339366004610d6b565b61078a565b61026d61034c366004610df3565b61080f565b6101d161035f366004610e66565b600460209081526000928352604080842090915290825290205481565b6000805461038990610e99565b80601f01602080910402602001604051908101604052809291908181526020018280546103b590610e99565b80156104025780601f106103d757610100808354040283529160200191610402565b820191906000526020600020905b8154815290600101906020018083116103e557829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906104729086815260200190565b60405180910390a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610517576104e58382610f1b565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff85166000908152600360205260408120805485929061054c908490610f1b565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906105b49087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146105fd576105f8610b2e565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f57484f000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6106d08282610bc8565b5050565b6001805461038990610e99565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610780576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f57484f000000000000000000000000000000000000000000000000000000000060448201526064016106bd565b6106d08282610c41565b336000908152600360205260408120805483919083906107ab908490610f1b565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906104729086815260200190565b42841015610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f4558504952454400000000000000000060448201526064016106bd565b600060016108856105c7565b73ffffffffffffffffffffffffffffffffffffffff8a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156109d7573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610a5257508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610ab8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e455200000000000000000000000000000000000060448201526064016106bd565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051610b609190610f32565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b8060026000828254610bda9190611008565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054839290610c76908490610f1b565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610c35565b600060208083528351808285015260005b81811015610cfc57858101830151858201604001528201610ce0565b81811115610d0e576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610d6657600080fd5b919050565b60008060408385031215610d7e57600080fd5b610d8783610d42565b946020939093013593505050565b600080600060608486031215610daa57600080fd5b610db384610d42565b9250610dc160208501610d42565b9150604084013590509250925092565b600060208284031215610de357600080fd5b610dec82610d42565b9392505050565b600080600080600080600060e0888a031215610e0e57600080fd5b610e1788610d42565b9650610e2560208901610d42565b95506040880135945060608801359350608088013560ff81168114610e4957600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215610e7957600080fd5b610e8283610d42565b9150610e9060208401610d42565b90509250929050565b600181811c90821680610ead57607f821691505b602082108103610ee6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610f2d57610f2d610eec565b500390565b600080835481600182811c915080831680610f4e57607f831692505b60208084108203610f86577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015610f9a5760018114610fcd57610ffa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952841515850289019650610ffa565b60008a81526020902060005b86811015610ff25781548b820152908501908301610fd9565b505084890196505b509498975050505050505050565b6000821982111561101b5761101b610eec565b50019056fea2646970667358221220653758a4eeb192901f490d1f6d898cb45abc9b2d4e7ec43281e1ed9b6a58de0764736f6c634300080f0033a2646970667358221220f08be87e614b60ae057c427a943141b87e3ebe881ef927f63cfcf068ccd9c36264736f6c634300080f0033
Verified Source Code Partial Match
Compiler: v0.8.15+commit.e14f2714
EVM: london
Optimization: Yes (1000000 runs)
BunniHub.sol 2732 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.15;
/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
error T();
error R();
/// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128
int24 internal constant MIN_TICK = -887272;
/// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128
int24 internal constant MAX_TICK = -MIN_TICK;
/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
uint160 internal constant MIN_SQRT_RATIO = 4295128739;
/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;
/// @notice Calculates sqrt(1.0001^tick) * 2^96
/// @dev Throws if |tick| > max tick
/// @param tick The input tick for the above formula
/// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)
/// at the given tick
function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
unchecked {
uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
if (absTick > uint256(int256(MAX_TICK))) revert T();
uint256 ratio = absTick & 0x1 != 0
? 0xfffcb933bd6fad37aa2d162d1a594001
: 0x100000000000000000000000000000000;
if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
if (tick > 0) ratio = type(uint256).max / ratio;
// this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
// we then downcast because we know the result always fits within 160 bits due to our tick input constraint
// we round up in the division so getTickAtSqrtRatio of the output price is always consistent
sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
}
}
/// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio
/// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may
/// ever return.
/// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96
/// @return tick The greatest tick for which the ratio is less than or equal to the input ratio
function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
unchecked {
// second inequality must be < because the price can never reach the price at the max tick
if (!(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO)) revert R();
uint256 ratio = uint256(sqrtPriceX96) << 32;
uint256 r = ratio;
uint256 msb = 0;
assembly {
let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(5, gt(r, 0xFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(4, gt(r, 0xFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(3, gt(r, 0xFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(2, gt(r, 0xF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(1, gt(r, 0x3))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := gt(r, 0x1)
msb := or(msb, f)
}
if (msb >= 128) r = ratio >> (msb - 127);
else r = ratio << (127 - msb);
int256 log_2 = (int256(msb) - 128) << 64;
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(63, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(62, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(61, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(60, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(59, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(58, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(57, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(56, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(55, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(54, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(53, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(52, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(51, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(50, f))
}
int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number
int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);
tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
}
}
}
/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
function mulDiv(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(a, b, not(0))
prod0 := mul(a, b)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
require(denominator > 0);
assembly {
result := div(prod0, denominator)
}
return result;
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (0 - denominator) & denominator;
// Divide denominator by power of two
assembly {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256
// Now that denominator is an odd number, it has an inverse
// modulo 2**256 such that denominator * inv = 1 mod 2**256.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // inverse mod 2**256
// Because the division is now exact we can divide by multiplying
// with the modular inverse of denominator. This will give us the
// correct result modulo 2**256. Since the precoditions guarantee
// that the outcome is less than 2**256, this is the final result.
// We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
function mulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
}
}
/// @title The interface for the Uniswap V3 Factory
/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees
interface IUniswapV3Factory {
/// @notice Emitted when the owner of the factory is changed
/// @param oldOwner The owner before the owner was changed
/// @param newOwner The owner after the owner was changed
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
/// @notice Emitted when a pool is created
/// @param token0 The first token of the pool by address sort order
/// @param token1 The second token of the pool by address sort order
/// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
/// @param tickSpacing The minimum number of ticks between initialized ticks
/// @param pool The address of the created pool
event PoolCreated(
address indexed token0,
address indexed token1,
uint24 indexed fee,
int24 tickSpacing,
address pool
);
/// @notice Emitted when a new fee amount is enabled for pool creation via the factory
/// @param fee The enabled fee, denominated in hundredths of a bip
/// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee
event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);
/// @notice Returns the current owner of the factory
/// @dev Can be changed by the current owner via setOwner
/// @return The address of the factory owner
function owner() external view returns (address);
/// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled
/// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context
/// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee
/// @return The tick spacing
function feeAmountTickSpacing(uint24 fee) external view returns (int24);
/// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
/// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
/// @param tokenA The contract address of either token0 or token1
/// @param tokenB The contract address of the other token
/// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
/// @return pool The pool address
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
/// @notice Creates a pool for the given two tokens and fee
/// @param tokenA One of the two tokens in the desired pool
/// @param tokenB The other of the two tokens in the desired pool
/// @param fee The desired fee for the pool
/// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved
/// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments
/// are invalid.
/// @return pool The address of the newly created pool
function createPool(
address tokenA,
address tokenB,
uint24 fee
) external returns (address pool);
/// @notice Updates the owner of the factory
/// @dev Must be called by the current owner
/// @param _owner The new owner of the factory
function setOwner(address _owner) external;
/// @notice Enables a fee amount with the given tickSpacing
/// @dev Fee amounts may never be removed once enabled
/// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)
/// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount
function enableFeeAmount(uint24 fee, int24 tickSpacing) external;
}
pragma abicoder v2;
/// @title Multicall interface
/// @notice Enables calling multiple methods in a single call to the contract
interface IMulticall {
/// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed
/// @dev The `msg.value` should not be trusted for any method callable from multicall.
/// @param data The encoded function data for each of the calls to make to this contract
/// @return results The results from each of the calls passed in via data
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
}
/// @title Multicall
/// @notice Enables calling multiple methods in a single call to the contract
abstract contract Multicall is IMulticall {
/// @inheritdoc IMulticall
function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) {
results = new bytes[](data.length);
for (uint256 i = 0; i < data.length; i++) {
(bool success, bytes memory result) = address(this).delegatecall(data[i]);
if (!success) {
// Next 5 lines from https://ethereum.stackexchange.com/a/83577
if (result.length < 68) revert();
assembly {
result := add(result, 0x04)
}
revert(abi.decode(result, (string)));
}
results[i] = result;
}
}
}
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
/// @title Self Permit
/// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route
interface ISelfPermit {
/// @notice Permits this contract to spend a given token from `msg.sender`
/// @dev The `owner` is always msg.sender and the `spender` is always address(this).
/// @param token The address of the token spent
/// @param value The amount that can be spent of token
/// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
function selfPermit(
address token,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external payable;
/// @notice Permits this contract to spend a given token from `msg.sender`
/// @dev The `owner` is always msg.sender and the `spender` is always address(this).
/// Can be used instead of #selfPermit to prevent calls from failing due to a frontrun of a call to #selfPermit
/// @param token The address of the token spent
/// @param value The amount that can be spent of token
/// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
function selfPermitIfNecessary(
address token,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external payable;
/// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter
/// @dev The `owner` is always msg.sender and the `spender` is always address(this)
/// @param token The address of the token spent
/// @param nonce The current nonce of the owner
/// @param expiry The timestamp at which the permit is no longer valid
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
function selfPermitAllowed(
address token,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) external payable;
/// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter
/// @dev The `owner` is always msg.sender and the `spender` is always address(this)
/// Can be used instead of #selfPermitAllowed to prevent calls from failing due to a frontrun of a call to #selfPermitAllowed.
/// @param token The address of the token spent
/// @param nonce The current nonce of the owner
/// @param expiry The timestamp at which the permit is no longer valid
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
function selfPermitAllowedIfNecessary(
address token,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) external payable;
}
/// @title Interface for permit
/// @notice Interface used by DAI/CHAI for permit
interface IERC20PermitAllowed {
/// @notice Approve the spender to spend some tokens via the holder signature
/// @dev This is the permit interface used by DAI and CHAI
/// @param holder The address of the token holder, the token owner
/// @param spender The address of the token spender
/// @param nonce The holder's nonce, increases at each call to permit
/// @param expiry The timestamp at which the permit is no longer valid
/// @param allowed Boolean that sets approval amount, true for type(uint256).max and false for 0
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
/// @title Self Permit
/// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route
/// @dev These functions are expected to be embedded in multicalls to allow EOAs to approve a contract and call a function
/// that requires an approval in a single transaction.
abstract contract SelfPermit is ISelfPermit {
/// @inheritdoc ISelfPermit
function selfPermit(
address token,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public payable override {
IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s);
}
/// @inheritdoc ISelfPermit
function selfPermitIfNecessary(
address token,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external payable override {
if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s);
}
/// @inheritdoc ISelfPermit
function selfPermitAllowed(
address token,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) public payable override {
IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s);
}
/// @inheritdoc ISelfPermit
function selfPermitAllowedIfNecessary(
address token,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) external payable override {
if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max)
selfPermitAllowed(token, nonce, expiry, v, r, s);
}
}
/// @title FixedPoint96
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
/// @dev Used in SqrtPriceMath.sol
library FixedPoint96 {
uint8 internal constant RESOLUTION = 96;
uint256 internal constant Q96 = 0x1000000000000000000000000;
}
/// @title Liquidity amount functions
/// @notice Provides functions for computing liquidity amounts from token amounts and prices
library LiquidityAmounts {
/// @notice Downcasts uint256 to uint128
/// @param x The uint258 to be downcasted
/// @return y The passed value, downcasted to uint128
function toUint128(uint256 x) private pure returns (uint128 y) {
require((y = uint128(x)) == x);
}
/// @notice Computes the amount of liquidity received for a given amount of token0 and price range
/// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param amount0 The amount0 being sent in
/// @return liquidity The amount of returned liquidity
function getLiquidityForAmount0(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint256 amount0
) internal pure returns (uint128 liquidity) {
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);
unchecked {
return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));
}
}
/// @notice Computes the amount of liquidity received for a given amount of token1 and price range
/// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param amount1 The amount1 being sent in
/// @return liquidity The amount of returned liquidity
function getLiquidityForAmount1(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint256 amount1
) internal pure returns (uint128 liquidity) {
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
unchecked {
return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));
}
}
/// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current
/// pool prices and the prices at the tick boundaries
/// @param sqrtRatioX96 A sqrt price representing the current pool prices
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param amount0 The amount of token0 being sent in
/// @param amount1 The amount of token1 being sent in
/// @return liquidity The maximum amount of liquidity received
function getLiquidityForAmounts(
uint160 sqrtRatioX96,
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint256 amount0,
uint256 amount1
) internal pure returns (uint128 liquidity) {
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
if (sqrtRatioX96 <= sqrtRatioAX96) {
liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);
} else if (sqrtRatioX96 < sqrtRatioBX96) {
uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);
uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);
liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;
} else {
liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);
}
}
/// @notice Computes the amount of token0 for a given amount of liquidity and a price range
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param liquidity The liquidity being valued
/// @return amount0 The amount of token0
function getAmount0ForLiquidity(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint128 liquidity
) internal pure returns (uint256 amount0) {
unchecked {
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
return
FullMath.mulDiv(
uint256(liquidity) << FixedPoint96.RESOLUTION,
sqrtRatioBX96 - sqrtRatioAX96,
sqrtRatioBX96
) / sqrtRatioAX96;
}
}
/// @notice Computes the amount of token1 for a given amount of liquidity and a price range
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param liquidity The liquidity being valued
/// @return amount1 The amount of token1
function getAmount1ForLiquidity(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint128 liquidity
) internal pure returns (uint256 amount1) {
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
unchecked {
return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);
}
}
/// @notice Computes the token0 and token1 value for a given amount of liquidity, the current
/// pool prices and the prices at the tick boundaries
/// @param sqrtRatioX96 A sqrt price representing the current pool prices
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param liquidity The liquidity being valued
/// @return amount0 The amount of token0
/// @return amount1 The amount of token1
function getAmountsForLiquidity(
uint160 sqrtRatioX96,
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint128 liquidity
) internal pure returns (uint256 amount0, uint256 amount1) {
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
if (sqrtRatioX96 <= sqrtRatioAX96) {
amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);
} else if (sqrtRatioX96 < sqrtRatioBX96) {
amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);
amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);
} else {
amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);
}
}
}
/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event OwnerUpdated(address indexed user, address indexed newOwner);
/*//////////////////////////////////////////////////////////////
OWNERSHIP STORAGE
//////////////////////////////////////////////////////////////*/
address public owner;
modifier onlyOwner() virtual {
require(msg.sender == owner, "UNAUTHORIZED");
_;
}
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(address _owner) {
owner = _owner;
emit OwnerUpdated(address(0), _owner);
}
/*//////////////////////////////////////////////////////////////
OWNERSHIP LOGIC
//////////////////////////////////////////////////////////////*/
function setOwner(address newOwner) public virtual onlyOwner {
owner = newOwner;
emit OwnerUpdated(msg.sender, newOwner);
}
}
/// @notice Library for converting between addresses and bytes32 values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Bytes32AddressLib.sol)
library Bytes32AddressLib {
function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {
return address(uint160(uint256(bytesValue)));
}
function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {
return bytes32(bytes20(addressValue));
}
}
/// @notice Deploy to deterministic addresses without an initcode factor.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol)
/// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol)
library CREATE3 {
using Bytes32AddressLib for bytes32;
//--------------------------------------------------------------------------------//
// Opcode | Opcode + Arguments | Description | Stack View //
//--------------------------------------------------------------------------------//
// 0x36 | 0x36 | CALLDATASIZE | size //
// 0x3d | 0x3d | RETURNDATASIZE | 0 size //
// 0x3d | 0x3d | RETURNDATASIZE | 0 0 size //
// 0x37 | 0x37 | CALLDATACOPY | //
// 0x36 | 0x36 | CALLDATASIZE | size //
// 0x3d | 0x3d | RETURNDATASIZE | 0 size //
// 0x34 | 0x34 | CALLVALUE | value 0 size //
// 0xf0 | 0xf0 | CREATE | newContract //
//--------------------------------------------------------------------------------//
// Opcode | Opcode + Arguments | Description | Stack View //
//--------------------------------------------------------------------------------//
// 0x67 | 0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode | bytecode //
// 0x3d | 0x3d | RETURNDATASIZE | 0 bytecode //
// 0x52 | 0x52 | MSTORE | //
// 0x60 | 0x6008 | PUSH1 08 | 8 //
// 0x60 | 0x6018 | PUSH1 18 | 24 8 //
// 0xf3 | 0xf3 | RETURN | //
//--------------------------------------------------------------------------------//
bytes internal constant PROXY_BYTECODE = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";
bytes32 internal constant PROXY_BYTECODE_HASH = keccak256(PROXY_BYTECODE);
function deploy(
bytes32 salt,
bytes memory creationCode,
uint256 value
) internal returns (address deployed) {
bytes memory proxyChildBytecode = PROXY_BYTECODE;
address proxy;
assembly {
// Deploy a new contract with our pre-made bytecode via CREATE2.
// We start 32 bytes into the code to avoid copying the byte length.
proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), salt)
}
require(proxy != address(0), "DEPLOYMENT_FAILED");
deployed = getDeployed(salt);
(bool success, ) = proxy.call{value: value}(creationCode);
require(success && deployed.code.length != 0, "INITIALIZATION_FAILED");
}
function getDeployed(bytes32 salt) internal view returns (address) {
address proxy = keccak256(
abi.encodePacked(
// Prefix:
bytes1(0xFF),
// Creator:
address(this),
// Salt:
salt,
// Bytecode hash:
PROXY_BYTECODE_HASH
)
).fromLast20Bytes();
return
keccak256(
abi.encodePacked(
// 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01)
// 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)
hex"d6_94",
proxy,
hex"01" // Nonce of the proxy contract (1)
)
).fromLast20Bytes();
}
}
/// @title Pool state that never changes
/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values
interface IUniswapV3PoolImmutables {
/// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface
/// @return The contract address
function factory() external view returns (address);
/// @notice The first of the two tokens of the pool, sorted by address
/// @return The token contract address
function token0() external view returns (address);
/// @notice The second of the two tokens of the pool, sorted by address
/// @return The token contract address
function token1() external view returns (address);
/// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
/// @return The fee
function fee() external view returns (uint24);
/// @notice The pool tick spacing
/// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive
/// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...
/// This value is an int24 to avoid casting even though it is always positive.
/// @return The tick spacing
function tickSpacing() external view returns (int24);
/// @notice The maximum amount of position liquidity that can use any tick in the range
/// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and
/// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool
/// @return The max amount of liquidity per tick
function maxLiquidityPerTick() external view returns (uint128);
}
/// @title Pool state that can change
/// @notice These methods compose the pool's state, and can change with any frequency including multiple times
/// per transaction
interface IUniswapV3PoolState {
/// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas
/// when accessed externally.
/// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value
/// @return tick The current tick of the pool, i.e. according to the last tick transition that was run.
/// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
/// boundary.
/// @return observationIndex The index of the last oracle observation that was written,
/// @return observationCardinality The current maximum number of observations stored in the pool,
/// @return observationCardinalityNext The next maximum number of observations, to be updated when the observation.
/// @return feeProtocol The protocol fee for both tokens of the pool.
/// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0
/// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.
/// unlocked Whether the pool is currently locked to reentrancy
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
/// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal0X128() external view returns (uint256);
/// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal1X128() external view returns (uint256);
/// @notice The amounts of token0 and token1 that are owed to the protocol
/// @dev Protocol fees will never exceed uint128 max in either token
function protocolFees() external view returns (uint128 token0, uint128 token1);
/// @notice The currently in range liquidity available to the pool
/// @dev This value has no relationship to the total liquidity across all ticks
/// @return The liquidity at the current price of the pool
function liquidity() external view returns (uint128);
/// @notice Look up information about a specific tick in the pool
/// @param tick The tick to look up
/// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or
/// tick upper
/// @return liquidityNet how much liquidity changes when the pool price crosses the tick,
/// @return feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,
/// @return feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,
/// @return tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick
/// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,
/// @return secondsOutside the seconds spent on the other side of the tick from the current tick,
/// @return initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.
/// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.
/// In addition, these values are only relative and must be used only in comparison to previous snapshots for
/// a specific position.
function ticks(int24 tick)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128,
int56 tickCumulativeOutside,
uint160 secondsPerLiquidityOutsideX128,
uint32 secondsOutside,
bool initialized
);
/// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information
function tickBitmap(int16 wordPosition) external view returns (uint256);
/// @notice Returns the information about a position by the position's key
/// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper
/// @return liquidity The amount of liquidity in the position,
/// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,
/// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick range a...
// [truncated — 117247 bytes total]
Read Contract
factory 0xc45a0155 → address
getBunniToken 0xba1db245 → address
owner 0x8da5cb5b → address
protocolFee 0xb0e21e8a → uint256
Write Contract 13 functions
These functions modify contract state and require a wallet transaction to execute.
compound 0x2a0f76ae
tuple key
returns: uint128, uint256, uint256
deployBunniToken 0x72f04a0a
tuple key
returns: address
deposit 0xe4ca5f40
tuple params
returns: uint256, uint128, uint256, uint256
multicall 0xac9650d8
bytes[] data
returns: bytes[]
selfPermit 0xf3995c67
address token
uint256 value
uint256 deadline
uint8 v
bytes32 r
bytes32 s
selfPermitAllowed 0x4659a494
address token
uint256 nonce
uint256 expiry
uint8 v
bytes32 r
bytes32 s
selfPermitAllowedIfNecessary 0xa4a78f0c
address token
uint256 nonce
uint256 expiry
uint8 v
bytes32 r
bytes32 s
selfPermitIfNecessary 0xc2e3140a
address token
uint256 value
uint256 deadline
uint8 v
bytes32 r
bytes32 s
setOwner 0x13af4035
address newOwner
setProtocolFee 0x787dce3d
uint256 value
sweepTokens 0x7071f0c4
address[] tokenList
address recipient
uniswapV3MintCallback 0xd3487997
uint256 amount0Owed
uint256 amount1Owed
bytes data
withdraw 0xa3c62f34
tuple params
returns: uint128, uint256, uint256
Token Balances (8)
View Transfers →Recent Transactions
No transactions found for this address