Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0xcB0bC7C879bb3E9CFEB9d8EFef653F33B3d242e9
Balance 0 ETH
Nonce 1
Code Size 21920 bytes
Indexed Transactions 0 (1 on-chain, 0.8% indexed)
External Etherscan · Sourcify

Contract Bytecode

21920 bytes
0x608060405234801561001057600080fd5b50600436106103575760003560e01c80637464fc3d116101c85780639610c5f111610104578063c45a0155116100a2578063d505accf1161007c578063d505accf14610a15578063dd62ed3e14610a28578063e852bc2e14610a53578063fff6cae914610a9257600080fd5b8063c45a0155146109c2578063c9738a0d146109e2578063d21220a7146109f557600080fd5b8063a9059cbb116100de578063a9059cbb14610943578063ba9a7a5614610956578063bc25cf771461095f578063bcaa64ea1461097257600080fd5b80639610c5f11461091157806396f2912714610931578063a1462c191461093957600080fd5b80637fa2ee6e11610171578063852a8dbe1161014b578063852a8dbe1461088f57806387353fed146108a257806389afcb44146108c257806395d89b41146108d557600080fd5b80637fa2ee6e1461082f57806381ca79981461083757806381fd0a461461084a57600080fd5b806378dd0298116101a257806378dd0298146107db5780637d316e28146107e35780637ecebe001461080f57600080fd5b80637464fc3d14610794578063748fc63b1461079d578063753bfd4b146107a657600080fd5b80632e0ae37511610297578063485cc955116102405780635909c0d51161021a5780635909c0d5146107515780635a3d5493146107595780636a6278421461076157806370a082311461077457600080fd5b8063485cc955146106cf5780634894c53c146106e25780634adc77c2146106f557600080fd5b80633644e515116102715780633644e5151461068b578063422fff051461069457806343c99081146106bc57600080fd5b80632e0ae3751461063757806330adf81f1461064a578063313ce5671461067157600080fd5b80630ece7236116103045780631fc2fa7f116102de5780631fc2fa7f1461059f57806323b872dd146105cc57806327e73836146105df5780632c8488da1461060d57600080fd5b80630ece72361461053c57806318160ddd146105755780631f4f5b421461058c57600080fd5b8063094cf14911610335578063094cf14914610429578063095ea7b3146104d45780630dfe1681146104f757600080fd5b8063022c0d9f1461035c57806306fdde03146103715780630902f1ac146103c3575b600080fd5b61036f61036a366004614e6d565b610a9a565b005b6103ad6040518060400160405280600b81526020017f467261787377617020563100000000000000000000000000000000000000000081525081565b6040516103ba9190614f33565b60405180910390f35b601e54604080516dffffffffffffffffffffffffffff80841682526e01000000000000000000000000000084041660208201527c010000000000000000000000000000000000000000000000000000000090920463ffffffff16908201526060016103ba565b61048d601e54601a546dffffffffffffffffffffffffffff808316936e0100000000000000000000000000008085048316947c0100000000000000000000000000000000000000000000000000000000900463ffffffff1693838116939190041690565b604080516dffffffffffffffffffffffffffff9687168152948616602086015263ffffffff909316928401929092528316606083015291909116608082015260a0016103ba565b6104e76104e2366004614f84565b6111a2565b60405190151581526020016103ba565b601c546105179073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103ba565b601a54610556906dffffffffffffffffffffffffffff1681565b6040516dffffffffffffffffffffffffffff90911681526020016103ba565b61057e60005481565b6040519081526020016103ba565b61036f61059a366004614fb0565b6111b8565b601a546104e7907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b6104e76105da366004614fc9565b6113b2565b6105f26105ed366004614fb0565b61148c565b604080519384526020840192909252908201526060016103ba565b61062061061b36600461500a565b6114bf565b6040805192151583526020830191909152016103ba565b61036f610645366004614fb0565b611520565b61057e7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b610679601281565b60405160ff90911681526020016103ba565b61057e60035481565b6106a76106a2366004614fb0565b611560565b604080519283526020830191909152016103ba565b6106a76106ca366004614fb0565b6115a6565b61036f6106dd36600461502c565b6115ec565b6106206106f0366004614fb0565b61168e565b610708610703366004614fb0565b6116ad565b6040805196875260208701959095529385019290925273ffffffffffffffffffffffffffffffffffffffff908116606085015290811660808401521660a082015260c0016103ba565b61057e61171f565b61057e611766565b61057e61076f366004615065565b6117ad565b61057e610782366004615065565b60016020526000908152604090205481565b61057e601f5481565b61057e60055481565b61057e6107b4366004615065565b73ffffffffffffffffffffffffffffffffffffffff16600090815260208052604090205490565b60185461057e565b601a54610556906e01000000000000000000000000000090046dffffffffffffffffffffffffffff1681565b61057e61081d366004615065565b60046020526000908152604090205481565b60215461057e565b61057e61084536600461500a565b611b37565b61085d610858366004614fb0565b611c9d565b60408051931515845273ffffffffffffffffffffffffffffffffffffffff9092166020840152908201526060016103ba565b61057e61089d366004614f84565b611e7e565b6108b56108b0366004615082565b611eae565b6040516103ba91906150b7565b6106a76108d0366004615065565b6120e5565b6103ad6040518060400160405280600581526020017f46532d563100000000000000000000000000000000000000000000000000000081525081565b61092461091f366004615065565b612595565b6040516103ba919061515b565b61036f61260c565b60075442146104e7565b6104e7610951366004614f84565b612738565b61057e6103e881565b61036f61096d366004615065565b612745565b610985610980366004614fb0565b612913565b604080516dffffffffffffffffffffffffffff9687168152948616602086015284019290925283166060830152909116608082015260a0016103ba565b601b546105179073ffffffffffffffffffffffffffffffffffffffff1681565b61057e6109f036600461500a565b612aa7565b601d546105179073ffffffffffffffffffffffffffffffffffffffff1681565b61036f610a2336600461519f565b612be2565b61057e610a3636600461502c565b600260209081526000928352604080842090915290825290205481565b600a54601154600754600654600b54601254604080519687526020870195909552938501929092526060840152608083015260a082015260c0016103ba565b61036f612e13565b602254600114610aa957600080fd5b6000602255610ab742612fda565b6000851180610ac65750600084115b610b37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303300000000000000000000000000000000000000000000000000000000604082015260600190565b60405180910390fd5b600080610b93601e546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b5091509150816dffffffffffffffffffffffffffff1687108015610bc65750806dffffffffffffffffffffffffffff1686105b610c2e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303400000000000000000000000000000000000000000000000000000000604082015260600190565b601c54601d54600091829173ffffffffffffffffffffffffffffffffffffffff918216919081169089168214801590610c9357508073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b610cfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303500000000000000000000000000000000000000000000000000000000604082015260600190565b8a15610d0c57610d0c828a8d61333e565b8915610d1d57610d1d818a8c61333e565b8615610db0576040517f10d1e85c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16906310d1e85c90610d7d9033908f908f908e908e90600401615216565b600060405180830381600087803b158015610d9757600080fd5b505af1158015610dab573d6000803e3d6000fd5b505050505b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526dffffffffffffffffffffffffffff9091169073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610e30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e54919061528e565b610e5e91906152d6565b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529195506e01000000000000000000000000000090046dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f15919061528e565b610f1f91906152d6565b92505050600089856dffffffffffffffffffffffffffff16610f4191906152d6565b8311610f4e576000610f72565b610f688a6dffffffffffffffffffffffffffff87166152d6565b610f7290846152d6565b90506000610f908a6dffffffffffffffffffffffffffff87166152d6565b8311610f9d576000610fc1565b610fb78a6dffffffffffffffffffffffffffff87166152d6565b610fc190846152d6565b90506000821180610fd25750600081115b61103a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303600000000000000000000000000000000000000000000000000000000604082015260600190565b60006110478360036152ed565b611053866103e86152ed565b61105d91906152d6565b9050600061106c8360036152ed565b611078866103e86152ed565b61108291906152d6565b90506110a16dffffffffffffffffffffffffffff808916908a166152ed565b6110ae90620f42406152ed565b6110b882846152ed565b1015611120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f4b000000000000000000000000000000000000000000000000000000000000006044820152606401610b2e565b505061112e848488886134e0565b60408051838152602081018390529081018c9052606081018b905273ffffffffffffffffffffffffffffffffffffffff8a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001602255505050505050505050565b60006111af338484613806565b50600192915050565b6022546001146111c757600080fd5b60006022556111d542612fda565b60008080806111e5600686613875565b601c549397509195509350915073ffffffffffffffffffffffffffffffffffffffff80841691161480611218578361121a565b815b601a805460009061123c9084906dffffffffffffffffffffffffffff1661532a565b92506101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff16021790555080611279578161127b565b835b601a8054600e906112af9084906e01000000000000000000000000000090046dffffffffffffffffffffffffffff1661532a565b82546dffffffffffffffffffffffffffff9182166101009390930a928302919092021990911617905550600086815260196020526040902060050180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905561133283338461333e565b61133d85338661333e565b6040805187815273ffffffffffffffffffffffffffffffffffffffff878116602083015291810186905290841660608201526080810183905233907f3c5d5e0947e8b8050cf53e91c7496de2499da1b7613ec86b8fda8705789663909060a00160405180910390a25050600160225550505050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526002602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146114775773ffffffffffffffffffffffffffffffffffffffff841660009081526002602090815260408083203384529091529020546114459083906152d6565b73ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020555b611482848484613916565b5060019392505050565b6021818154811061149c57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b60008060066012015484106114d357600080fd5b6000848152601960205260408120600401546115079060069073ffffffffffffffffffffffffffffffffffffffff166139e5565b9050611514818686613a21565b90969095509350505050565b60225460011461152f57600080fd5b600060225560075481108015906115465750428111155b61154f57600080fd5b61155881612fda565b506001602255565b6000806000600660000154846115769190615388565b61158090856152d6565b6000908152600c6020908152604080832054601390925290912054909590945092505050565b6000806000600660000154846115bc9190615388565b6115c690856152d6565b600090815260106020908152604080832054601790925290912054909590945092505050565b601b5473ffffffffffffffffffffffffffffffffffffffff16331461161057600080fd5b601c80547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff858116918217909355601d805483169385169384179055600554600880548416909217909155600980549092169092179055426007556006555050565b5050565b60008061169a42611520565b6116a483426114bf565b91509150915091565b60008060008060008060066012015487106116c757600080fd5b50505060009384525050601960205250604090208054600182015460028301546003840154600485015460059095015493959294919373ffffffffffffffffffffffffffffffffffffffff9182169392821692911690565b60215460009061172f5750600090565b6021805461173f906001906152d6565b8154811061174f5761174f61539c565b906000526020600020906003020160010154905090565b6021546000906117765750600090565b60218054611786906001906152d6565b815481106117965761179661539c565b906000526020600020906003020160020154905090565b60006022546001146117be57600080fd5b60006022556117cc42612fda565b600080611828601e546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50601a54601c546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529395509193506000926dffffffffffffffffffffffffffff9091169173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156118b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d8919061528e565b6118e291906152d6565b601a54601d546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529293506000926e0100000000000000000000000000009092046dffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561197d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a1919061528e565b6119ab91906152d6565b905060006119c96dffffffffffffffffffffffffffff8616846152d6565b905060006119e76dffffffffffffffffffffffffffff8616846152d6565b905060006119f58787613af8565b60008054919250819003611a36576103e8611a18611a1385876152ed565b613c65565b611a2291906152d6565b9850611a3160006103e8613cd5565b611a8b565b611a886dffffffffffffffffffffffffffff8916611a5483876152ed565b611a5e91906153cb565b6dffffffffffffffffffffffffffff8916611a7984876152ed565b611a8391906153cb565b613d80565b98505b60008911611a9857600080fd5b611aa28a8a613cd5565b611aae86868a8a6134e0565b8115611ae957601e54611ae5906dffffffffffffffffffffffffffff6e0100000000000000000000000000008204811691166152ed565b601f555b604080518581526020810185905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a25050600160225550949695505050505050565b6000602254600114611b4857600080fd5b6000602255601a547c0100000000000000000000000000000000000000000000000000000000900460ff1615611b7d57600080fd5b611b8642612fda565b6000611b9184613d96565b905080601a600e8282829054906101000a90046dffffffffffffffffffffffffffff16611bbe91906153df565b82546101009290920a6dffffffffffffffffffffffffffff818102199093169183160217909155601a54601e54919250611c12916e0100000000000000000000000000009182900484169190048316615411565b1115611c1d57600080fd5b611c2960068285613ef2565b336000818152602080805260408083208054600181018255908452928290209092018490558151848152908101859052908101869052919350907fe1ce07267c05b1609d3bd4046ca369b74e64cd2b45ee8321ccc79783252c60b4906060015b60405180910390a250600160225592915050565b6000806000602254600114611cb157600080fd5b6000602255611cbf42612fda565b60008080611cce600688613f2e565b601c54929550909350915073ffffffffffffffffffffffffffffffffffffffff90811690841603611d5557601a8054839190600090611d1e9084906dffffffffffffffffffffffffffff1661532a565b92506101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff160217905550611db3565b81601a600e8282829054906101000a90046dffffffffffffffffffffffffffff16611d80919061532a565b92506101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff1602179055505b8015611e0857600087815260196020526040902060050180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790555b611e1383338461333e565b604080518881526020810184905282151581830152905173ffffffffffffffffffffffffffffffffffffffff85169133917f43168622ddb54ed84ccad30626ace7077235dc531c67aaf639752c45195354489181900360600190a36001602255969195509350915050565b602080528160005260406000208181548110611e9957600080fd5b90600052602060002001600091509150505481565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208080526040808320805482518185028101850190935280835260609493830182828015611f1857602002820191906000526020600020905b815481526020019060010190808311611f04575b505050505090506000848251611f2e91906152d6565b90506000611f3c8583613d80565b90508067ffffffffffffffff811115611f5757611f57615429565b604051908082528060200260200182016040528015611fdc57816020015b6040805160e08101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611f755790505b50935060005b818110156120da576019600085611ff9848b615411565b815181106120095761200961539c565b6020908102919091018101518252818101929092526040908101600020815160e08101835281548152600182015493810193909352600281015491830191909152600381015473ffffffffffffffffffffffffffffffffffffffff908116606084015260048201548116608084015260059091015490811660a083015274010000000000000000000000000000000000000000900460ff16151560c082015285518690839081106120bc576120bc61539c565b602002602001018190525080806120d290615458565b915050611fe2565b505050509392505050565b6000806022546001146120f757600080fd5b600060225561210542612fda565b600080612161601e546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50601c54601d54601a546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015294965092945073ffffffffffffffffffffffffffffffffffffffff918216939116916000916dffffffffffffffffffffffffffff9091169084906370a0823190602401602060405180830381865afa1580156121f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221b919061528e565b61222591906152d6565b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529192506000916e0100000000000000000000000000009091046dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156122bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e0919061528e565b6122ea91906152d6565b306000908152600160205260408120549192506123078888613af8565b6000549091508061231886856152ed565b61232291906153cb565b9a508061232f85856152ed565b61233991906153cb565b995060008b11801561234b575060008a115b61235457600080fd5b61235e3084613fc5565b612369878d8d61333e565b612374868d8c61333e565b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526dffffffffffffffffffffffffffff9091169073ffffffffffffffffffffffffffffffffffffffff8916906370a0823190602401602060405180830381865afa1580156123f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612418919061528e565b61242291906152d6565b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529196506e01000000000000000000000000000090046dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8816906370a0823190602401602060405180830381865afa1580156124b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d9919061528e565b6124e391906152d6565b93506124f185858b8b6134e0565b811561252c57601e54612528906dffffffffffffffffffffffffffff6e0100000000000000000000000000008204811691166152ed565b601f555b604080518c8152602081018c905273ffffffffffffffffffffffffffffffffffffffff8e169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050505050505050506001602281905550915091565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080805260409182902080548351818402810184019094528084526060939283018282801561260057602002820191906000526020600020905b8154815260200190600101908083116125ec575b50505050509050919050565b601b54604080517f094b74150000000000000000000000000000000000000000000000000000000081529051339273ffffffffffffffffffffffffffffffffffffffff169163094b74159160048083019260209291908290030181865afa15801561267b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269f9190615490565b73ffffffffffffffffffffffffffffffffffffffff16146126bf57600080fd5b601a547c0100000000000000000000000000000000000000000000000000000000900460ff16156126ef57600080fd5b601a80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c0100000000000000000000000000000000000000000000000000000000179055565b60006111af338484613916565b60225460011461275457600080fd5b600060225561276242612fda565b601c54601d54601a54601e5473ffffffffffffffffffffffffffffffffffffffff938416939092169161286291849186916127b0916dffffffffffffffffffffffffffff91821691166153df565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526dffffffffffffffffffffffffffff919091169073ffffffffffffffffffffffffffffffffffffffff8716906370a08231906024015b602060405180830381865afa15801561282f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612853919061528e565b61285d91906152d6565b61333e565b601a54601e5461290991839186916128a3916dffffffffffffffffffffffffffff6e01000000000000000000000000000092839004811692909104166153df565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526dffffffffffffffffffffffffffff919091169073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401612812565b5050600160225550565b600754601a54601e5460009283929091839182918291612946916dffffffffffffffffffffffffffff91821691166153df565b601a54601e54919250600091612986916dffffffffffffffffffffffffffff6e0100000000000000000000000000009182900481169291909104166153df565b90506129f760405180610120016040528060006dffffffffffffffffffffffffffff16815260200160006dffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b601e546dffffffffffffffffffffffffffff80821683526e0100000000000000000000000000009182900481166020840152601a54808216604085015291909104166060820152612a4a60068a83614078565b6040810151612a69906dffffffffffffffffffffffffffff85166152d6565b97508060600151826dffffffffffffffffffffffffffff16612a8b91906152d6565b9650806040015194508060600151935050505091939590929450565b6000602254600114612ab857600080fd5b6000602255601a547c0100000000000000000000000000000000000000000000000000000000900460ff1615612aed57600080fd5b612af642612fda565b6000612b01846141fc565b601a80549192508291600090612b289084906dffffffffffffffffffffffffffff166153df565b82546101009290920a6dffffffffffffffffffffffffffff818102199093169183160217909155601a54601e54919250612b6791908316908316615411565b1115612b7257600080fd5b612b7e60068285614311565b336000818152602080805260408083208054600181018255908452928290209092018490558151848152908101859052908101869052919350907f9971294258b76b481032b9c1f7f5594619d7cf40e29e224de9e71481bd0a4f8590606001611c89565b42841015612bef57600080fd5b60035473ffffffffffffffffffffffffffffffffffffffff8816600090815260046020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087612c4f83615458565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001612cf09291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015612d79573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590612df457508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b612dfd57600080fd5b612e08898989613806565b505050505050505050565b602254600114612e2257600080fd5b6000602255612e3042612fda565b601a54601c546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152612fd3926dffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed8919061528e565b612ee291906152d6565b601a54601d546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526e0100000000000000000000000000009092046dffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b919061528e565b612fa591906152d6565b601e546dffffffffffffffffffffffffffff808216916e0100000000000000000000000000009004166134e0565b6001602255565b601a547c0100000000000000000000000000000000000000000000000000000000900460ff16156130085750565b60075442036130145750565b61308360405180610120016040528060006dffffffffffffffffffffffffffff16815260200160006dffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b601e546dffffffffffffffffffffffffffff80821683526e0100000000000000000000000000009182900481166020840152601a548082166040850152919091041660608201526130d660068383614345565b6040810151601a805460608401516dffffffffffffffffffffffffffff9081166e010000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090921693169290921791909117905580516020820151600061314f64010000000086615388565b601e5490915063ffffffff7c010000000000000000000000000000000000000000000000000000000090910481168203908116158015906131d65750601e546dffffffffffffffffffffffffffff85811691161415806131d65750601e546dffffffffffffffffffffffffffff8481166e0100000000000000000000000000009092041614155b156132e3577f793ee8b0d8020fc042a920607e3cbd37f5132c011786c8dd10a685f4414ed3818286600001518760200151886040015189606001518a608001518b60a001518c60c001518d60e001518e610100015160405161329c9a9998979695949392919063ffffffff9a909a168a526dffffffffffffffffffffffffffff98891660208b01529690971660408901526060880194909452608087019290925260a086015260c085015260e08401526101008301919091526101208201526101400190565b60405180910390a1601e546132de906dffffffffffffffffffffffffffff8087169186821691818116916e0100000000000000000000000000009004166134e0565b613336565b601e80546dffffffffffffffffffffffffffff8581166e010000000000000000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909216908716171790555b505050505050565b604080518082018252601981527f7472616e7366657228616464726573732c75696e743235362900000000000000602091820152815173ffffffffffffffffffffffffffffffffffffffff85811660248301526044808301869052845180840390910181526064909201845291810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839287169161340591906154ad565b6000604051808303816000865af19150503d8060008114613442576040519150601f19603f3d011682016040523d82523d6000602084013e613447565b606091505b509150915081801561347157508051158061347157508080602001905181019061347191906154c9565b6134d9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303100000000000000000000000000000000000000000000000000000000604082015260600190565b5050505050565b601a546dffffffffffffffffffffffffffff906134ff90821686615411565b1115801561353c5750601a546dffffffffffffffffffffffffffff90613539906e0100000000000000000000000000009004821685615411565b11155b6135a4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303200000000000000000000000000000000000000000000000000000000604082015260600190565b60006135b564010000000042615388565b601e5490915063ffffffff7c0100000000000000000000000000000000000000000000000000000000909104811682039081161580159061360557506dffffffffffffffffffffffffffff841615155b801561362057506dffffffffffffffffffffffffffff831615155b1561371657602160405180606001604052808463ffffffff1681526020018363ffffffff1661367688613652896144ec565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169061451d565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160261369d61171f565b0181526020018363ffffffff166136b7876136528a6144ec565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16026136de611766565b019052815460018181018455600093845260209384902083516003909302019182559282015192810192909255604001516002909101555b601e805463ffffffff84167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8981166e0100000000000000000000000000009081027fffffffff000000000000000000000000000000000000000000000000000000009095168c83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600081815260138301602052604081206005810154600482015473ffffffffffffffffffffffffffffffffffffffff90811693929116908290816138b988876139e5565b90506138ca81888a60010154614539565b6003840154919650935073ffffffffffffffffffffffffffffffffffffffff1633148015613902575060008511806139025750600083115b61390b57600080fd5b505092959194509250565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260409020546139479082906152d6565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160205260408082209390935590841681522054613984908290615411565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906138689085815260200190565b600282015460009073ffffffffffffffffffffffffffffffffffffffff838116911614613a155782600b01613a1a565b826004015b9392505050565b6000828152600484016020526040812054819080613a3e57600080fd5b600085815260038701602090815260408083205460058a019092529091205481861115613a9d5760008281526006890160205260409020546e010000000000000000000000000000620f42408383038602040494506001955050613aed565b6e010000000000000000000000000000620f42406dffffffffffffffffffffffffffff1684838b60010154030281613ad757613ad7615359565b0481613ae557613ae5615359565b049350600094505b505050935093915050565b600080601b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8c9190615490565b601f5473ffffffffffffffffffffffffffffffffffffffff8216158015945091925090613c51578015613c4c576000613bdb611a136dffffffffffffffffffffffffffff8088169089166152ed565b90506000613be883613c65565b905080821115613c49576000613bfe82846152d6565b600054613c0b91906152ed565b9050600082613c1b8560056152ed565b613c259190615411565b90506000613c3382846153cb565b90508015613c4557613c458782613cd5565b5050505b50505b613c5d565b8015613c5d576000601f555b505092915050565b60006003821115613cc65750806000613c7f6002836153cb565b613c8a906001615411565b90505b81811015613cc057905080600281613ca581866153cb565b613caf9190615411565b613cb991906153cb565b9050613c8d565b50919050565b8115613cd0575060015b919050565b80600054613ce39190615411565b600090815573ffffffffffffffffffffffffffffffffffffffff8316815260016020526040902054613d16908290615411565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90613d749085815260200190565b60405180910390a35050565b6000818310613d8f5781613a1a565b5090919050565b601d546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600091829173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015613e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e2d919061528e565b601d54909150613e559073ffffffffffffffffffffffffffffffffffffffff1633308661462b565b601d546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829173ffffffffffffffffffffffffffffffffffffffff16906370a08231906024015b602060405180830381865afa158015613ec4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ee8919061528e565b613a1a91906152d6565b60038301546002840154600091613f2691869173ffffffffffffffffffffffffffffffffffffffff908116911686866147c2565b949350505050565b600081815260138301602052604081206005810154600482015473ffffffffffffffffffffffffffffffffffffffff9182169392839290918391613f74918991166139e5565b9050613f8581878960010154614a2a565b6003840154919550935073ffffffffffffffffffffffffffffffffffffffff1633148015613fb35750600084115b613fbc57600080fd5b50509250925092565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260016020526040902054613ff69082906152d6565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260408120919091555461402b9082906152d6565b600090815560405182815273ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001613d74565b6001830154835460008161408c8185615388565b61409690856152d6565b6140a09190615411565b600487018054600b8901805493945091925b888510156141925760008581526002850160205260409020541515806140e75750600085815260028401602052604090205415155b156141815760006140f888876152d6565b90506000620f424061410a83866152ed565b61411491906153cb565b90506000620f424061412684866152ed565b61413091906153cb565b905061413d8b8383614a77565b5050600088815260028801602052604090205461415a90866152d6565b600089815260028801602052604090205490955061417890856152d6565b93508799505050505b61418b8686615411565b94506140b2565b8887146141f05760006141a5888b6152d6565b90506000620f42406141b783866152ed565b6141c191906153cb565b90506000620f42406141d384866152ed565b6141dd91906153cb565b90506141ea8b8383614a77565b50505050505b50505050505050505050565b601c546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600091829173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561426f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614293919061528e565b601c549091506142bb9073ffffffffffffffffffffffffffffffffffffffff1633308661462b565b601c546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401613ea7565b60028301546003840154600091613f2691869173ffffffffffffffffffffffffffffffffffffffff908116911686866147c2565b600183015483546000816143598185615388565b61436390856152d6565b61436d9190615411565b905060048601600b87015b868310156144585760008381526002830160205260409020541515806143ad5750600083815260028201602052604090205415155b156144475760006143be86856152d6565b8354909150600090620f4240906143d69084906152ed565b6143e091906153cb565b8354909150600090620f4240906143f89085906152ed565b61440291906153cb565b90506000806144128b8585614a77565b915091506144208782614c0c565b61442a8683614c0c565b6144348789614c49565b61443e8689614c49565b87995050505050505b6144518484615411565b9250614378565b8685146144dd57600061446b86896152d6565b8354909150600090620f4240906144839084906152ed565b61448d91906153cb565b8354909150600090620f4240906144a59085906152ed565b6144af91906153cb565b90506000806144bf8b8585614a77565b915091506144cd8782614c0c565b6144d78683614c0c565b50505050505b50505050506001929092015550565b60006145176e0100000000000000000000000000006dffffffffffffffffffffffffffff84166154eb565b92915050565b6000613a1a6dffffffffffffffffffffffffffff83168461552f565b6000828152600384016020526040812054819083811161455857600080fd5b6000858152600487016020526040902054620f42408161457887856152d6565b61458291906152ed565b61458c91906153cb565b600087815260058901602052604090205460018901549195506e01000000000000000000000000000091620f4240919003830204049250808760000160008282546145d791906152d6565b90915550506000868152600488016020908152604080832083905560038a01825280832083905584835260028a019091528120805483929061461a9084906152d6565b925050819055505050935093915050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916146ca91906154ad565b6000604051808303816000865af19150503d8060008114614707576040519150601f19603f3d011682016040523d82523d6000602084013e61470c565b606091505b509150915081801561473657508051158061473657508080602001905181019061473691906154c9565b613336576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610b2e565b8454600090429082906147d59083615388565b6147df90836152d6565b90506000816147ef866001615411565b8a546147fb91906152ed565b6148059190615411565b9050600061481384836152d6565b61482088620f42406152ed565b61482a91906153cb565b90506000811161483957600080fd5b60006148458b8b6139e5565b9050614857818c601201548486614c89565b6040518060e001604052808c6012015481526020018481526020018381526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152602001600015158152508b60130160008d60120154815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160050160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060c08201518160050160146101000a81548160ff0219169083151502179055509050508a6012016000815480929190614a1790615458565b909155509b9a5050505050505050505050565b600080614a38858585613a21565b925090508015614a58576000848152600486016020526040812055614a6f565b600185015460008581526005870160205260409020555b935093915050565b6000806000856040015186600001516dffffffffffffffffffffffffffff16614aa09190615411565b90506000866060015187602001516dffffffffffffffffffffffffffff16614ac89190615411565b9050614afe87600001516dffffffffffffffffffffffffffff1688602001516dffffffffffffffffffffffffffff168888614cfd565b604089015191955093508690614b15908690615411565b614b1f91906152d6565b604088015260608701518590614b36908590615411565b614b4091906152d6565b60608801526040870151614b5490836152d6565b6dffffffffffffffffffffffffffff1687526060870151614b7590826152d6565b6dffffffffffffffffffffffffffff166020880152608087018051859190614b9e908390615411565b90525060a087018051849190614bb5908390615411565b90525060c087018051879190614bcc908390615411565b90525060e087018051869190614be3908390615411565b9052506101008701805160019190614bfc908390615411565b9052509296919550909350505050565b81541561168a578154700f42400000000000000000000000000000820281614c3657614c36615359565b6001939093018054919093040190915550565b6000818152600283016020526040812054835490918491614c6b9084906152d6565b90915550506001820154600091825260069092016020526040902055565b81846000016000828254614c9d9190615411565b9091555050600184015460008481526005860160209081526040808320939093556003870181528282208490556004870181528282208590558382526002870190529081208054849290614cf2908490615411565b909155505050505050565b60008060018411801590614d12575060018311155b614e3f5760018411614d61576000614d2c846103e56152ed565b905080614d3b876103e86152ed565b614d459190615411565b614d4f82896152ed565b614d5991906153cb565b925050614e3f565b60018311614dac576000614d77856103e56152ed565b905080614d86886103e86152ed565b614d909190615411565b614d9a82886152ed565b614da491906153cb565b915050614e3f565b60006103e8614dbd866103e56152ed565b614dc791906153cb565b614dd19088615411565b905060006103e8614de4866103e56152ed565b614dee91906153cb565b614df89088615411565b905080614e0583896152ed565b614e0f91906153cb565b614e1990836152d6565b935081614e26828a6152ed565b614e3091906153cb565b614e3a90826152d6565b925050505b94509492505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614e6a57600080fd5b50565b600080600080600060808688031215614e8557600080fd5b85359450602086013593506040860135614e9e81614e48565b9250606086013567ffffffffffffffff80821115614ebb57600080fd5b818801915088601f830112614ecf57600080fd5b813581811115614ede57600080fd5b896020828501011115614ef057600080fd5b9699959850939650602001949392505050565b60005b83811015614f1e578181015183820152602001614f06565b83811115614f2d576000848401525b50505050565b6020815260008251806020840152614f52816040850160208701614f03565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215614f9757600080fd5b8235614fa281614e48565b946020939093013593505050565b600060208284031215614fc257600080fd5b5035919050565b600080600060608486031215614fde57600080fd5b8335614fe981614e48565b92506020840135614ff981614e48565b929592945050506040919091013590565b6000806040838503121561501d57600080fd5b50508035926020909101359150565b6000806040838503121561503f57600080fd5b823561504a81614e48565b9150602083013561505a81614e48565b809150509250929050565b60006020828403121561507757600080fd5b8135613a1a81614e48565b60008060006060848603121561509757600080fd5b83356150a281614e48565b95602085013595506040909401359392505050565b602080825282518282018190526000919060409081850190868401855b8281101561514e578151805185528681015187860152858101518686015260608082015173ffffffffffffffffffffffffffffffffffffffff9081169187019190915260808083015182169087015260a0808301519091169086015260c09081015115159085015260e090930192908501906001016150d4565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561519357835183529284019291840191600101615177565b50909695505050505050565b600080600080600080600060e0888a0312156151ba57600080fd5b87356151c581614e48565b965060208801356151d581614e48565b95506040880135945060608801359350608088013560ff811681146151f957600080fd5b9699959850939692959460a0840135945060c09093013592915050565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101949350505050565b6000602082840312156152a057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156152e8576152e86152a7565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615325576153256152a7565b500290565b60006dffffffffffffffffffffffffffff83811690831681811015615351576153516152a7565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261539757615397615359565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000826153da576153da615359565b500490565b60006dffffffffffffffffffffffffffff808316818516808303821115615408576154086152a7565b01949350505050565b60008219821115615424576154246152a7565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615489576154896152a7565b5060010190565b6000602082840312156154a257600080fd5b8151613a1a81614e48565b600082516154bf818460208701614f03565b9190910192915050565b6000602082840312156154db57600080fd5b81518015158114613a1a57600080fd5b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff80831681851681830481118215151615615526576155266152a7565b02949350505050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8084168061555e5761555e615359565b9216919091049291505056fea2646970667358221220bdc5b014c6704437df24db228c555db8616bb6648c9811f54a9e45271265b6f564736f6c634300080d0033

Verified Source Code Partial Match

Compiler: v0.8.13+commit.abaa5c0e EVM: london Optimization: Yes (100000 runs)
FraxswapPair.sol 1479 lines
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

// Sources flattened with hardhat v2.9.3 https://hardhat.org

// File contracts/Fraxswap/core/interfaces/IUniswapV2PairPartialV5.sol


interface IUniswapV2PairPartialV5 {
    //    event Approval(address indexed owner, address indexed spender, uint value);
    //    event Transfer(address indexed from, address indexed to, uint value);
    //
    //    function name() external pure returns (string memory);
    //    function symbol() external pure returns (string memory);
    //    function decimals() external pure returns (uint8);
    //    function totalSupply() external view returns (uint);
    //    function balanceOf(address owner) external view returns (uint);
    //    function allowance(address owner, address spender) external view returns (uint);
    //
    //    function approve(address spender, uint value) external returns (bool);
    //    function transfer(address to, uint value) external returns (bool);
    //    function transferFrom(address from, address to, uint value) external returns (bool);
    //
    //    function DOMAIN_SEPARATOR() external view returns (bytes32);
    //    function PERMIT_TYPEHASH() external pure returns (bytes32);
    //    function nonces(address owner) external view returns (uint);
    //
    //    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;
    function initialize(address, address) external;

    // TWAMM

    function longTermSwapFrom0To1(uint256 amount0In, uint256 numberOfTimeIntervals) external returns (uint256 orderId);
    function longTermSwapFrom1To0(uint256 amount1In, uint256 numberOfTimeIntervals) external returns (uint256 orderId);
    function cancelLongTermSwap(uint256 orderId) external;
    function withdrawProceedsFromLongTermSwap(uint256 orderId) external returns (bool is_expired, address rewardTkn, uint256 totalReward);
    function executeVirtualOrders(uint256 blockTimestamp) external;

    function orderTimeInterval() external returns (uint256);
    function getTWAPHistoryLength() external view returns (uint);
    function getTwammReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast, uint112 _twammReserve0, uint112 _twammReserve1);
    function getReserveAfterTwamm(uint256 blockTimestamp) external view returns (uint112 _reserve0, uint112 _reserve1, uint256 lastVirtualOrderTimestamp, uint112 _twammReserve0, uint112 _twammReserve1);
    function getNextOrderID() external view returns (uint256);
    function getOrderIDsForUser(address user) external view returns (uint256[] memory);
    function getOrderIDsForUserLength(address user) external view returns (uint256);
    //    function getDetailedOrdersForUser(address user, uint256 offset, uint256 limit) external view returns (LongTermOrdersLib.Order[] memory detailed_orders);
    function twammUpToDate() external view returns (bool);
    function getTwammState() external view returns (uint256 token0Rate, uint256 token1Rate, uint256 lastVirtualOrderTimestamp, uint256 orderTimeInterval_rtn, uint256 rewardFactorPool0, uint256 rewardFactorPool1);
    function getTwammSalesRateEnding(uint256 _blockTimestamp) external view returns (uint256 orderPool0SalesRateEnding, uint256 orderPool1SalesRateEnding);
    function getTwammRewardFactor(uint256 _blockTimestamp) external view returns (uint256 rewardFactorPool0AtTimestamp, uint256 rewardFactorPool1AtTimestamp);
    function getTwammOrder(uint256 orderId) external view returns (uint256 id, uint256 expirationTimestamp, uint256 saleRate, address owner, address sellTokenAddr, address buyTokenAddr);
    function getTwammOrderProceedsView(uint256 orderId, uint256 blockTimestamp) external view returns (bool orderExpired, uint256 totalReward);
    function getTwammOrderProceeds(uint256 orderId) external returns (bool orderExpired, uint256 totalReward);


    function togglePauseNewSwaps() external;
}


// File contracts/Fraxswap/core/interfaces/IUniswapV2ERC20V5.sol


interface IUniswapV2ERC20V5 {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}


// File contracts/Fraxswap/core/FraxswapERC20.sol


// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ========================== FraxswapERC20 ===========================
// ====================================================================
// Fraxswap ERC-20
// Inspired by https://www.paradigm.xyz/2021/07/twamm
// https://github.com/para-dave/twamm

// Frax Finance: https://github.com/FraxFinance

// Primary Author(s)
// Rich Gee: https://github.com/zer0blockchain
// Dennis: https://github.com/denett

// Logic / Algorithm Ideas
// FrankieIsLost: https://github.com/FrankieIsLost

// Reviewer(s) / Contributor(s)
// Travis Moore: https://github.com/FortisFortuna
// Sam Kazemian: https://github.com/samkazemian
// Drake Evans: https://github.com/DrakeEvans
// Jack Corddry: https://github.com/corddry
// Justin Moore: https://github.com/0xJM
contract FraxswapERC20 is IUniswapV2ERC20V5 {

    string public constant override name = 'Fraxswap V1';
    string public constant override symbol = 'FS-V1';
    uint8 public constant override decimals = 18;
    uint  public override totalSupply;
    mapping(address => uint) public override balanceOf;
    mapping(address => mapping(address => uint)) public override allowance;

    bytes32 public override DOMAIN_SEPARATOR;
    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 public constant override PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
    mapping(address => uint) public override nonces;

    constructor() public {
        uint chainId = block.chainid;
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                keccak256(bytes(name)),
                keccak256(bytes('1')),
                chainId,
                address(this)
            )
        );
    }

    function _mint(address to, uint value) internal {
        totalSupply = totalSupply + value;
        balanceOf[to] = balanceOf[to] + value;
        emit Transfer(address(0), to, value);
    }

    function _burn(address from, uint value) internal {
        balanceOf[from] = balanceOf[from] - value;
        totalSupply = totalSupply - value;
        emit Transfer(from, address(0), value);
    }

    function _approve(address owner, address spender, uint value) private {
        allowance[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    function _transfer(address from, address to, uint value) private {
        balanceOf[from] = balanceOf[from] - value;
        balanceOf[to] = balanceOf[to] + value;
        emit Transfer(from, to, value);
    }

    function approve(address spender, uint value) external override returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function transfer(address to, uint value) external override returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(address from, address to, uint value) external override returns (bool) {
        if (allowance[from][msg.sender] != type(uint).max) {
            allowance[from][msg.sender] = allowance[from][msg.sender] - value;
        }
        _transfer(from, to, value);
        return true;
    }

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external override {
        require(deadline >= block.timestamp); // EXPIRED
        bytes32 digest = keccak256(
            abi.encodePacked(
                '\x19\x01',
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
            )
        );
        address recoveredAddress = ecrecover(digest, v, r, s);
        require(recoveredAddress != address(0) && recoveredAddress == owner); // INVALID_SIGNATURE
        _approve(owner, spender, value);
    }
}


// File contracts/Fraxswap/core/libraries/Math.sol


// a library for performing various math operations

library Math {
    function min(uint x, uint y) internal pure returns (uint z) {
        z = x < y ? x : y;
    }

    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrt(uint y) internal pure returns (uint z) {
        if (y > 3) {
            z = y;
            uint x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }
}


// File contracts/Fraxswap/core/libraries/UQ112x112.sol


// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))

// range: [0, 2**112 - 1]
// resolution: 1 / 2**112

library UQ112x112 {
    uint224 constant Q112 = 2**112;

    // encode a uint112 as a UQ112x112
    function encode(uint112 y) internal pure returns (uint224 z) {
        z = uint224(y) * Q112; // never overflows
    }

    // divide a UQ112x112 by a uint112, returning a UQ112x112
    function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
        z = x / uint224(y);
    }
}


// File contracts/Fraxswap/core/interfaces/IERC20V5.sol


interface IERC20V5 {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);
}


// File contracts/Fraxswap/core/interfaces/IUniswapV2FactoryV5.sol


interface IUniswapV2FactoryV5 {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    function feeTo() external view returns (address);
    function feeToSetter() external view returns (address);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs(uint) external view returns (address pair);
    function allPairsLength() external view returns (uint);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
}


// File contracts/Fraxswap/core/interfaces/IUniswapV2CalleeV5.sol


interface IUniswapV2CalleeV5 {
    function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
}


// File contracts/Fraxswap/libraries/TransferHelper.sol



// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::safeApprove: approve failed'
        );
    }

    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::safeTransfer: transfer failed'
        );
    }

    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::transferFrom: transferFrom failed'
        );
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
    }
}


// File contracts/Fraxswap/twamm/ExecVirtualOrders.sol


// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ======================= ExecVirtualOrdersLib =======================
// ====================================================================
// TWAMM logic for executing the virtual orders
// Inspired by https://www.paradigm.xyz/2021/07/twamm
// https://github.com/para-dave/twamm

// Frax Finance: https://github.com/FraxFinance

// Primary Author(s)
// Rich Gee: https://github.com/zer0blockchain
// Dennis: https://github.com/denett

// Logic / Algorithm Ideas
// FrankieIsLost: https://github.com/FrankieIsLost

// Reviewer(s) / Contributor(s)
// Travis Moore: https://github.com/FortisFortuna
// Sam Kazemian: https://github.com/samkazemian
// Drake Evans: https://github.com/DrakeEvans
// Jack Corddry: https://github.com/corddry
// Justin Moore: https://github.com/0xJM

///@notice This library handles the execution of long term orders.
library ExecVirtualOrdersLib {

    ///@notice computes the result of virtual trades by the token pools
    function computeVirtualBalances(
        uint256 token0Start,
        uint256 token1Start,
        uint256 token0In,
        uint256 token1In)
    internal pure returns (uint256 token0Out, uint256 token1Out)
    {
        token0Out = 0;
        token1Out = 0;
        //if no tokens are sold to the pool, we don't need to execute any orders
        if (token0In <= 1 && token1In <= 1) {
            // do nothing
        }
        //in the case where only one pool is selling, we just perform a normal swap
        else if (token0In <= 1) {
            //constant product formula
            uint token1InWithFee = token1In * 997;
            token0Out = token0Start * token1InWithFee / ((token1Start * 1000) + token1InWithFee);
        }
        else if (token1In <= 1) {
            //contant product formula
            uint token0InWithFee = token0In * 997;
            token1Out = token1Start * token0InWithFee / ((token0Start * 1000) + token0InWithFee);
        }
        //when both pools sell, we use the TWAMM formula
        else {
            uint256 newToken0 = token0Start + (token0In * 997 / 1000);
            uint256 newToken1 = token1Start + (token1In * 997 / 1000);
            token0Out = newToken0 - (token1Start * (newToken0) / (newToken1));
            token1Out = newToken1 - (token0Start * (newToken1) / (newToken0));
        }
    }
}


// File contracts/Fraxswap/twamm/LongTermOrders.sol


// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ========================= LongTermOrdersLib ========================
// ====================================================================
// TWAMM long term order execution logic
// Inspired by https://www.paradigm.xyz/2021/07/twamm
// https://github.com/para-dave/twamm

// Frax Finance: https://github.com/FraxFinance

// Primary Author(s)
// Rich Gee: https://github.com/zer0blockchain
// Dennis: https://github.com/denett

// Logic / Algorithm Ideas
// FrankieIsLost: https://github.com/FrankieIsLost

// Reviewer(s) / Contributor(s)
// Travis Moore: https://github.com/FortisFortuna
// Sam Kazemian: https://github.com/samkazemian
// Drake Evans: https://github.com/DrakeEvans
// Jack Corddry: https://github.com/corddry
// Justin Moore: https://github.com/0xJM

///@notice This library handles the state and execution of long term orders. 
library LongTermOrdersLib {

    using LongTermOrdersLib for OrderPool;

    /// ---------------------------
    /// ----- LongTerm Orders -----
    /// ---------------------------

    uint112 internal constant SELL_RATE_ADDITIONAL_PRECISION = 1000000;

    ///@notice information associated with a long term order
    ///fields should NOT be changed after Order struct is created
    struct Order {
        uint256 id;
        uint256 expirationTimestamp;
        uint256 saleRate;
        address owner;
        address sellTokenAddr;
        address buyTokenAddr;
        bool isComplete;
    }

    ///@notice structure contains full state related to long term orders
    struct LongTermOrders {

        ///@notice minimum time interval between order expiries
        uint256 orderTimeInterval;

        ///@notice last virtual orders were executed immediately before this block.timestamp
        uint256 lastVirtualOrderTimestamp;

        ///@notice token pair being traded in embedded amm
        address token0;
        address token1;

        ///@notice mapping from token address to pool that is selling that token
        ///we maintain two order pools, one for each token that is tradable in the AMM
        OrderPool OrderPool0;
        OrderPool OrderPool1;

        ///@notice incrementing counter for order ids, this is the next order id
        uint256 orderId;

        ///@notice mapping from order ids to Orders
        mapping(uint256 => Order) orderMap;
    }

    struct ExecuteVirtualOrdersResult {
        uint112 newReserve0;
        uint112 newReserve1;
        uint256 newTwammReserve0;
        uint256 newTwammReserve1;
        uint256 token0Bought;
        uint256 token1Bought;
        uint256 token0Sold;
        uint256 token1Sold;
        uint256 expiries;
    }

    ///@notice initialize state
    function initialize(LongTermOrders storage longTermOrders,
        address token0,
        address token1,
        uint256 lastVirtualOrderTimestamp,
        uint256 orderTimeInterval) internal {
        longTermOrders.token0 = token0;
        longTermOrders.token1 = token1;
        longTermOrders.lastVirtualOrderTimestamp = lastVirtualOrderTimestamp;
        longTermOrders.orderTimeInterval = orderTimeInterval;
    }

    ///@notice get the OrderPool for this token
    function getOrderPool(LongTermOrders storage longTermOrders, address token) internal view returns (OrderPool storage orderPool) {
        orderPool = token == longTermOrders.token0 ? longTermOrders.OrderPool0 : longTermOrders.OrderPool1;
    }

    ///@notice swap token 0 for token 1. Amount represents total amount being sold, numberOfTimeIntervals determines when order expires
    function longTermSwapFrom0To1(LongTermOrders storage longTermOrders, uint256 amount0, uint256 numberOfTimeIntervals) internal returns (uint256) {
        return performLongTermSwap(longTermOrders, longTermOrders.token0, longTermOrders.token1, amount0, numberOfTimeIntervals);
    }

    ///@notice swap token 1 for token 0. Amount represents total amount being sold, numberOfTimeIntervals determines when order expires
    function longTermSwapFrom1To0(LongTermOrders storage longTermOrders, uint256 amount1, uint256 numberOfTimeIntervals) internal returns (uint256) {
        return performLongTermSwap(longTermOrders, longTermOrders.token1, longTermOrders.token0, amount1, numberOfTimeIntervals);
    }

    ///@notice adds long term swap to order pool
    function performLongTermSwap(LongTermOrders storage longTermOrders, address from, address to, uint256 amount, uint256 numberOfTimeIntervals) private returns (uint256) {
        // make sure to update virtual order state (before calling this function)

        //determine the selling rate based on number of blocks to expiry and total amount
        uint256 currentTime = block.timestamp;
        uint256 lastExpiryTimestamp = currentTime - (currentTime % longTermOrders.orderTimeInterval);
        uint256 orderExpiry = longTermOrders.orderTimeInterval * (numberOfTimeIntervals + 1) + lastExpiryTimestamp;
        uint256 sellingRate = SELL_RATE_ADDITIONAL_PRECISION * amount / (orderExpiry - currentTime);

        require(sellingRate > 0); // tokenRate cannot be zero

        //add order to correct pool
        OrderPool storage orderPool = getOrderPool(longTermOrders, from);
        orderPoolDepositOrder(orderPool, longTermOrders.orderId, sellingRate, orderExpiry);

        //add to order map
        longTermOrders.orderMap[longTermOrders.orderId] = Order(longTermOrders.orderId, orderExpiry, sellingRate, msg.sender, from, to, false);
        return longTermOrders.orderId++;
    }

    ///@notice cancel long term swap, pay out unsold tokens and well as purchased tokens
    function cancelLongTermSwap(LongTermOrders storage longTermOrders, uint256 orderId) internal returns (address sellToken, uint256 unsoldAmount, address buyToken, uint256 purchasedAmount) {
        // make sure to update virtual order state (before calling this function)

        Order storage order = longTermOrders.orderMap[orderId];
        buyToken = order.buyTokenAddr;
        sellToken = order.sellTokenAddr;

        OrderPool storage orderPool = getOrderPool(longTermOrders, sellToken);
        (unsoldAmount, purchasedAmount) = orderPoolCancelOrder(orderPool, orderId, longTermOrders.lastVirtualOrderTimestamp);

        require(order.owner == msg.sender && (unsoldAmount > 0 || purchasedAmount > 0)); // owner and amounts check

    }

    ///@notice withdraw proceeds from a long term swap (can be expired or ongoing)
    function withdrawProceedsFromLongTermSwap(LongTermOrders storage longTermOrders, uint256 orderId) internal returns (address proceedToken, uint256 proceeds, bool orderExpired) {
        // make sure to update virtual order state (before calling this function)

        Order storage order = longTermOrders.orderMap[orderId];
        proceedToken = order.buyTokenAddr;

        OrderPool storage orderPool = getOrderPool(longTermOrders, order.sellTokenAddr);
        (proceeds, orderExpired) = orderPoolWithdrawProceeds(orderPool, orderId, longTermOrders.lastVirtualOrderTimestamp);

        require(order.owner == msg.sender && proceeds > 0); // owner and amounts check
    }

    ///@notice executes all virtual orders between current lastVirtualOrderTimestamp and blockTimestamp
    //also handles orders that expire at end of final blockTimestamp. This assumes that no orders expire inside the given interval
    function executeVirtualTradesAndOrderExpiries(
        ExecuteVirtualOrdersResult memory reserveResult,
        uint256 token0SellAmount,
        uint256 token1SellAmount
    ) private view returns (uint256 token0Out, uint256 token1Out) {

        //initial amm balance
        uint256 bal0 = reserveResult.newReserve0 + reserveResult.newTwammReserve0;
        uint256 bal1 = reserveResult.newReserve1 + reserveResult.newTwammReserve1;

        //updated balances from sales
        (token0Out, token1Out) = ExecVirtualOrdersLib.computeVirtualBalances(
            reserveResult.newReserve0,
            reserveResult.newReserve1,
            token0SellAmount,
            token1SellAmount
        );

        //update balances reserves
        reserveResult.newTwammReserve0 = reserveResult.newTwammReserve0 + token0Out - token0SellAmount;
        reserveResult.newTwammReserve1 = reserveResult.newTwammReserve1 + token1Out - token1SellAmount;
        reserveResult.newReserve0 = uint112(bal0 - reserveResult.newTwammReserve0); // calculate reserve0 incl LP fees
        reserveResult.newReserve1 = uint112(bal1 - reserveResult.newTwammReserve1); // calculate reserve1 incl LP fees
        reserveResult.token0Bought += token0Out;
        reserveResult.token1Bought += token1Out;
        reserveResult.token0Sold += token0SellAmount;
        reserveResult.token1Sold += token1SellAmount;
        reserveResult.expiries += 1;
    }

    ///@notice executes all virtual orders until blockTimestamp is reached.
    function executeVirtualOrdersUntilTimestamp(LongTermOrders storage longTermOrders, uint256 blockTimestamp, ExecuteVirtualOrdersResult memory reserveResult) internal {

        uint256 lastVirtualOrderTimestampLocal = longTermOrders.lastVirtualOrderTimestamp; // save gas
        uint256 orderTimeInterval = longTermOrders.orderTimeInterval; // save gas
        uint256 nextExpiryBlockTimestamp = lastVirtualOrderTimestampLocal - (lastVirtualOrderTimestampLocal % orderTimeInterval) + orderTimeInterval;
        //iterate through time intervals eligible for order expiries, moving state forward

        OrderPool storage orderPool0 = longTermOrders.OrderPool0;
        OrderPool storage orderPool1 = longTermOrders.OrderPool1;

        while (nextExpiryBlockTimestamp < blockTimestamp) {
            // Optimization for skipping blocks with no expiry
            if (orderPool0.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp] > 0
                || orderPool1.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp] > 0) {

                //amount sold from virtual trades
                uint256 blockTimestampElapsed = nextExpiryBlockTimestamp - lastVirtualOrderTimestampLocal;
                uint256 token0SellAmount = orderPool0.currentSalesRate * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION;
                uint256 token1SellAmount = orderPool1.currentSalesRate * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION;

                (uint256 token0Out, uint256 token1Out) = executeVirtualTradesAndOrderExpiries(reserveResult, token0SellAmount, token1SellAmount);

                //distribute proceeds to pools. make sure to call this before orderPoolUpdateStateFromTimestampExpiry.
                orderPoolDistributePayment(orderPool0, token1Out);
                orderPoolDistributePayment(orderPool1, token0Out);

                //handle orders expiring at end of interval. call orderPoolDistributePayment before calling this.
                orderPoolUpdateStateFromTimestampExpiry(orderPool0, nextExpiryBlockTimestamp);
                orderPoolUpdateStateFromTimestampExpiry(orderPool1, nextExpiryBlockTimestamp);

                lastVirtualOrderTimestampLocal = nextExpiryBlockTimestamp;
            }
            nextExpiryBlockTimestamp += orderTimeInterval;
        }
        //finally, move state to current blockTimestamp if necessary
        if (lastVirtualOrderTimestampLocal != blockTimestamp) {

            //amount sold from virtual trades
            uint256 blockTimestampElapsed = blockTimestamp - lastVirtualOrderTimestampLocal;
            uint256 token0SellAmount = orderPool0.currentSalesRate * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION;
            uint256 token1SellAmount = orderPool1.currentSalesRate * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION;

            (uint256 token0Out, uint256 token1Out) = executeVirtualTradesAndOrderExpiries(reserveResult, token0SellAmount, token1SellAmount);

            //distribute proceeds to pools
            orderPoolDistributePayment(orderPool0, token1Out);
            orderPoolDistributePayment(orderPool1, token0Out);

            // skip call to orderPoolUpdateStateFromTimestampExpiry, this will not be an expiry timestamp. save gas
        }

        longTermOrders.lastVirtualOrderTimestamp = blockTimestamp;
    }

    ///@notice executes all virtual orders until blockTimestamp is reached (AS A VIEW)
    function executeVirtualOrdersUntilTimestampView(LongTermOrders storage longTermOrders, uint256 blockTimestamp, ExecuteVirtualOrdersResult memory reserveResult) internal view {

        uint256 lastVirtualOrderTimestampLocal = longTermOrders.lastVirtualOrderTimestamp; // save gas
        uint256 orderTimeInterval = longTermOrders.orderTimeInterval; // save gas
        uint256 nextExpiryBlockTimestamp = lastVirtualOrderTimestampLocal - (lastVirtualOrderTimestampLocal % orderTimeInterval) + orderTimeInterval;
        //iterate through time intervals eligible for order expiries, moving state forward

        OrderPool storage orderPool0 = longTermOrders.OrderPool0;
        OrderPool storage orderPool1 = longTermOrders.OrderPool1;

        // currentSales for each pool is mutated in the non-view (mutate locally)
        uint256 currentSalesRate0 = orderPool0.currentSalesRate;
        uint256 currentSalesRate1 = orderPool1.currentSalesRate;

        while (nextExpiryBlockTimestamp < blockTimestamp) {
            // Optimization for skipping blocks with no expiry
            if (orderPool0.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp] > 0
                || orderPool1.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp] > 0) {

                //amount sold from virtual trades
                uint256 blockTimestampElapsed = nextExpiryBlockTimestamp - lastVirtualOrderTimestampLocal;
                uint256 token0SellAmount = currentSalesRate0 * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION;
                uint256 token1SellAmount = currentSalesRate1 * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION;

                executeVirtualTradesAndOrderExpiries(reserveResult, token0SellAmount, token1SellAmount);

                currentSalesRate0 -= orderPool0.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp];
                currentSalesRate1 -= orderPool1.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp];

                lastVirtualOrderTimestampLocal = nextExpiryBlockTimestamp;
            }
            nextExpiryBlockTimestamp += orderTimeInterval;
        }
        //finally, move state to current blockTimestamp if necessary
        if (lastVirtualOrderTimestampLocal != blockTimestamp) {

            //amount sold from virtual trades
            uint256 blockTimestampElapsed = blockTimestamp - lastVirtualOrderTimestampLocal;
            uint256 token0SellAmount = currentSalesRate0 * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION;
            uint256 token1SellAmount = currentSalesRate1 * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION;

            executeVirtualTradesAndOrderExpiries(reserveResult, token0SellAmount, token1SellAmount);

        }
    }

    /// ---------------------------
    /// -------- OrderPool --------
    /// ---------------------------

    ///@notice An Order Pool is an abstraction for a pool of long term orders that sells a token at a constant rate to the embedded AMM.
    ///the order pool handles the logic for distributing the proceeds from these sales to the owners of the long term orders through a modified
    ///version of the staking algorithm from  https://uploads-ssl.webflow.com/5ad71ffeb79acc67c8bcdaba/5ad8d1193a40977462982470_scalable-reward-distribution-paper.pdf

    uint256 constant Q112 = 2**112;

    ///@notice you can think of this as a staking pool where all long term orders are staked.
    /// The pool is paid when virtual long term orders are executed, and each order is paid proportionally
    /// by the order's sale rate per time intervals
    struct OrderPool {
        ///@notice current rate that tokens are being sold (per time interval)
        uint256 currentSalesRate;

        ///@notice sum of (salesProceeds_k / salesRate_k) over every period k. Stored as a fixed precision floating point number
        uint256 rewardFactor;

        ///@notice this maps time interval numbers to the cumulative sales rate of orders that expire on that block (time interval)
        mapping(uint256 => uint256) salesRateEndingPerTimeInterval;

        ///@notice map order ids to the block timestamp in which they expire
        mapping(uint256 => uint256) orderExpiry;

        ///@notice map order ids to their sales rate
        mapping(uint256 => uint256) salesRate;

        ///@notice reward factor per order at time of submission
        mapping(uint256 => uint256) rewardFactorAtSubmission;

        ///@notice reward factor at a specific time interval
        mapping(uint256 => uint256) rewardFactorAtTimestamp;
    }

    ///@notice distribute payment amount to pool (in the case of TWAMM, proceeds from trades against amm)
    function orderPoolDistributePayment(OrderPool storage orderPool, uint256 amount) internal {
        if (orderPool.currentSalesRate != 0) {
            unchecked { // Addition is with overflow
                orderPool.rewardFactor += amount * Q112 * SELL_RATE_ADDITIONAL_PRECISION / orderPool.currentSalesRate;
            }
        }
    }

    ///@notice deposit an order into the order pool.
    function orderPoolDepositOrder(OrderPool storage orderPool, uint256 orderId, uint256 amountPerInterval, uint256 orderExpiry) internal {
        orderPool.currentSalesRate += amountPerInterval;
        orderPool.rewardFactorAtSubmission[orderId] = orderPool.rewardFactor;
        orderPool.orderExpiry[orderId] = orderExpiry;
        orderPool.salesRate[orderId] = amountPerInterval;
        orderPool.salesRateEndingPerTimeInterval[orderExpiry] += amountPerInterval;
    }

    ///@notice when orders expire after a given timestamp, we need to update the state of the pool
    function orderPoolUpdateStateFromTimestampExpiry(OrderPool storage orderPool, uint256 blockTimestamp) internal {
        orderPool.currentSalesRate -= orderPool.salesRateEndingPerTimeInterval[blockTimestamp];
        orderPool.rewardFactorAtTimestamp[blockTimestamp] = orderPool.rewardFactor;
    }

    ///@notice cancel order and remove from the order pool
    function orderPoolCancelOrder(OrderPool storage orderPool, uint256 orderId, uint256 blockTimestamp) internal returns (uint256 unsoldAmount, uint256 purchasedAmount) {
        uint256 expiry = orderPool.orderExpiry[orderId];
        require(expiry > blockTimestamp);

        //calculate amount that wasn't sold, and needs to be returned
        uint256 salesRate = orderPool.salesRate[orderId];
        unsoldAmount = (expiry - blockTimestamp) * salesRate / SELL_RATE_ADDITIONAL_PRECISION;

        //calculate amount of other token that was purchased
        unchecked { // subtraction is with underflow
            purchasedAmount = ((orderPool.rewardFactor - orderPool.rewardFactorAtSubmission[orderId]) * salesRate / SELL_RATE_ADDITIONAL_PRECISION) / Q112;
        }

        //update state
        orderPool.currentSalesRate -= salesRate;
        orderPool.salesRate[orderId] = 0;
        orderPool.orderExpiry[orderId] = 0;
        orderPool.salesRateEndingPerTimeInterval[expiry] -= salesRate;
    }

    ///@notice withdraw proceeds from pool for a given order. This can be done before or after the order has expired.
    //If the order has expired, we calculate the reward factor at time of expiry. If order has not yet expired, we
    //use current reward factor, and update the reward factor at time of staking (effectively creating a new order)
    function orderPoolWithdrawProceeds(OrderPool storage orderPool, uint256 orderId, uint256 blockTimestamp) internal returns (uint256 totalReward, bool orderExpired) {
        (orderExpired, totalReward) = orderPoolGetProceeds(orderPool, orderId, blockTimestamp);

        if (orderExpired) {
            //remove stake
            orderPool.salesRate[orderId] = 0;
        }
        //if order has not yet expired, we just adjust the start
        else {
            orderPool.rewardFactorAtSubmission[orderId] = orderPool.rewardFactor;
        }
    }

    ///@notice view function for getting the current proceeds for the given order
    function orderPoolGetProceeds(OrderPool storage orderPool, uint256 orderId, uint256 blockTimestamp) internal view returns (bool orderExpired, uint256 totalReward) {
        uint256 stakedAmount = orderPool.salesRate[orderId];
        require(stakedAmount > 0);
        uint256 orderExpiry = orderPool.orderExpiry[orderId];
        uint256 rewardFactorAtSubmission = orderPool.rewardFactorAtSubmission[orderId];

        //if order has expired, we need to calculate the reward factor at expiry
        if (blockTimestamp > orderExpiry) {
            uint256 rewardFactorAtExpiry = orderPool.rewardFactorAtTimestamp[orderExpiry];
            unchecked { // subtraction is with underflow
                totalReward = ((rewardFactorAtExpiry - rewardFactorAtSubmission) * stakedAmount / SELL_RATE_ADDITIONAL_PRECISION) / Q112;
            }
            orderExpired = true;
        }
        else {
            unchecked { // subtraction is with underflow
                totalReward = ((orderPool.rewardFactor - rewardFactorAtSubmission) * stakedAmount / SELL_RATE_ADDITIONAL_PRECISION) / Q112;
            }
            orderExpired = false;
        }
    }
}


// File contracts/Fraxswap/core/FraxswapPair.sol


// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// =========================== FraxswapPair ===========================
// ====================================================================
// TWAMM LP Pair Token
// Inspired by https://www.paradigm.xyz/2021/07/twamm
// https://github.com/para-dave/twamm

// Frax Finance: https://github.com/FraxFinance

// Primary Author(s)
// Rich Gee: https://github.com/zer0blockchain
// Dennis: https://github.com/denett

// Logic / Algorithm Ideas
// FrankieIsLost: https://github.com/FrankieIsLost

// Reviewer(s) / Contributor(s)
// Travis Moore: https://github.com/FortisFortuna
// Sam Kazemian: https://github.com/samkazemian
// Drake Evans: https://github.com/DrakeEvans
// Jack Corddry: https://github.com/corddry
// Justin Moore: https://github.com/0xJM









contract FraxswapPair is IUniswapV2PairPartialV5, FraxswapERC20 {
    using UQ112x112 for uint224;
    using LongTermOrdersLib for LongTermOrdersLib.LongTermOrders;
    using LongTermOrdersLib for LongTermOrdersLib.ExecuteVirtualOrdersResult;

    /// ---------------------------
    /// -----TWAMM Parameters -----
    /// ---------------------------

    // address public owner_address;

    ///@notice time interval that are eligible for order expiry (to align expiries)
    uint256 public orderTimeInterval = 3600;

    ///@notice data structure to handle long term orders
    LongTermOrdersLib.LongTermOrders internal longTermOrders;

    uint112 public twammReserve0;
    uint112 public twammReserve1;

    bool public newSwapsPaused;

    modifier execVirtualOrders() {
        executeVirtualOrdersInternal(block.timestamp);
        _;
    }

    /// ---------------------------
    /// -------- Modifiers --------
    /// ---------------------------

    ///@notice Throws if called by any account other than the owner.
    modifier onlyOwner() {
        require(IUniswapV2FactoryV5(factory).feeToSetter() == msg.sender); // NOT OWNER
        _;
    }

    ///@notice Checks if new swaps are paused. If they are, only allow closing of existing ones.
    modifier isNotPaused() {
        require(newSwapsPaused == false); // NEW LT ORDERS PAUSED
        _;
    }

    /// ---------------------------
    /// --------- Events ----------
    /// ---------------------------

    ///@notice An event emitted when a long term swap from token0 to token1 is performed
    event LongTermSwap0To1(address indexed addr, uint256 orderId, uint256 amount0In, uint256 numberOfTimeIntervals);

    ///@notice An event emitted when a long term swap from token1 to token0 is performed
    event LongTermSwap1To0(address indexed addr, uint256 orderId, uint256 amount1In, uint256 numberOfTimeIntervals);

    ///@notice An event emitted when a long term swap is cancelled
    event CancelLongTermOrder(address indexed addr, uint256 orderId, address sellToken, uint256 unsoldAmount, address buyToken, uint256 purchasedAmount);

    ///@notice An event emitted when a long term swap is withdrawn
    event WithdrawProceedsFromLongTermOrder(address indexed addr, uint256 orderId, address indexed proceedToken, uint256 proceeds, bool orderExpired);

    ///@notice An event emitted when virtual orders are executed
    event VirtualOrderExecution(uint256 blocktimestamp, uint256 newReserve0, uint256 newReserve1, uint256 newTwammReserve0, uint256 newTwammReserve1, uint256 token0Bought, uint256 token1Bought, uint256 token0Sold, uint256 token1Sold, uint256 expiries);

    /// -------------------------------
    /// -----UNISWAPV2 Parameters -----
    /// -------------------------------

    uint public constant override MINIMUM_LIQUIDITY = 10 ** 3;
    bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));

    address public override factory;
    address public override token0;
    address public override token1;

    uint112 private reserve0;           // uses single storage slot, accessible via getReserves
    uint112 private reserve1;           // uses single storage slot, accessible via getReserves

    uint32  private blockTimestampLast; // uses single storage slot, accessible via getReserves

    uint public override kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event

    // Track order IDs
    mapping(address => uint256[]) public orderIDsForUser;

    TWAPObservation[] public TWAPObservationHistory;

    struct TWAPObservation {
        uint timestamp;
        uint price0CumulativeLast;
        uint price1CumulativeLast;
    }
    function price0CumulativeLast() public view override returns (uint){
        return TWAPObservationHistory.length > 0 ? TWAPObservationHistory[TWAPObservationHistory.length - 1].price0CumulativeLast : 0;
    }
    function price1CumulativeLast() public view override returns (uint){
        return TWAPObservationHistory.length > 0 ? TWAPObservationHistory[TWAPObservationHistory.length - 1].price1CumulativeLast : 0;
    }
    function getTWAPHistoryLength() public view override returns (uint){
        return TWAPObservationHistory.length;
    }

    uint private unlocked = 1;
    modifier lock() {
        require(unlocked == 1); // LOCKED
        unlocked = 0;
        _;
        unlocked = 1;
    }

    function getOrderIDsForUser(address user) external view returns (uint256[] memory) {
        return orderIDsForUser[user];
    }

    function getOrderIDsForUserLength(address user) external view returns (uint256) {
        return orderIDsForUser[user].length;
    }

    function getDetailedOrdersForUser(address user, uint256 offset, uint256 limit) external view returns (LongTermOrdersLib.Order[] memory detailed_orders) {
        uint256[] memory order_ids = orderIDsForUser[user];
        uint256 length_remaining = order_ids.length - offset;
        uint256 limit_to_use = Math.min(limit, length_remaining);
        detailed_orders = new LongTermOrdersLib.Order[](limit_to_use);

        for (uint256 i = 0; i < limit_to_use; i++){ 
            detailed_orders[i] = longTermOrders.orderMap[order_ids[offset + i]];
        }
    }

    function getReserves() public override view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
        return (reserve0, reserve1, blockTimestampLast);
    }

    function getTwammReserves() public override view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast, uint112 _twammReserve0, uint112 _twammReserve1) {
        return (reserve0, reserve1, blockTimestampLast, twammReserve0, twammReserve1);
    }

    function _safeTransfer(address token, address to, uint value) private {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "EC01"); // TRANSFER_FAILED
    }

    constructor() public {
        factory = msg.sender;
        // owner_address = IUniswapV2FactoryV5(factory).feeToSetter();
    }

    // called once by the factory at time of deployment
    function initialize(address _token0, address _token1) external override {
        require(msg.sender == factory); // FORBIDDEN
        // sufficient check
        token0 = _token0;
        token1 = _token1;

        // TWAMM
        longTermOrders.initialize(_token0, _token1, block.timestamp, orderTimeInterval);
    }

    // update reserves and, on the first call per block, price accumulators
    function _update(uint balance0, uint balance1, uint112 _reserve0, ...

// [truncated — 70214 bytes total]

Read Contract

DOMAIN_SEPARATOR 0x3644e515 → bytes32
MINIMUM_LIQUIDITY 0xba9a7a56 → uint256
PERMIT_TYPEHASH 0x30adf81f → bytes32
TWAPObservationHistory 0x27e73836 → uint256, uint256, uint256
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
decimals 0x313ce567 → uint8
factory 0xc45a0155 → address
getDetailedOrdersForUser 0x87353fed → tuple[]
getNextOrderID 0x78dd0298 → uint256
getOrderIDsForUser 0x9610c5f1 → uint256[]
getOrderIDsForUserLength 0x753bfd4b → uint256
getReserveAfterTwamm 0xbcaa64ea → uint112, uint112, uint256, uint112, uint112
getReserves 0x0902f1ac → uint112, uint112, uint32
getTWAPHistoryLength 0x7fa2ee6e → uint256
getTwammOrder 0x4adc77c2 → uint256, uint256, uint256, address, address, address
getTwammOrderProceedsView 0x2c8488da → bool, uint256
getTwammReserves 0x094cf149 → uint112, uint112, uint32, uint112, uint112
getTwammRewardFactor 0x43c99081 → uint256, uint256
getTwammSalesRateEnding 0x422fff05 → uint256, uint256
getTwammState 0xe852bc2e → uint256, uint256, uint256, uint256, uint256, uint256
kLast 0x7464fc3d → uint256
name 0x06fdde03 → string
newSwapsPaused 0x1fc2fa7f → bool
nonces 0x7ecebe00 → uint256
orderIDsForUser 0x852a8dbe → uint256
orderTimeInterval 0x748fc63b → uint256
price0CumulativeLast 0x5909c0d5 → uint256
price1CumulativeLast 0x5a3d5493 → uint256
symbol 0x95d89b41 → string
token0 0x0dfe1681 → address
token1 0xd21220a7 → address
totalSupply 0x18160ddd → uint256
twammReserve0 0x0ece7236 → uint112
twammReserve1 0x7d316e28 → uint112
twammUpToDate 0xa1462c19 → bool

Write Contract 17 functions

These functions modify contract state and require a wallet transaction to execute.

approve 0x095ea7b3
address spender
uint256 value
returns: bool
burn 0x89afcb44
address to
returns: uint256, uint256
cancelLongTermSwap 0x1f4f5b42
uint256 orderId
executeVirtualOrders 0x2e0ae375
uint256 blockTimestamp
getTwammOrderProceeds 0x4894c53c
uint256 orderId
returns: bool, uint256
initialize 0x485cc955
address _token0
address _token1
longTermSwapFrom0To1 0xc9738a0d
uint256 amount0In
uint256 numberOfTimeIntervals
returns: uint256
longTermSwapFrom1To0 0x81ca7998
uint256 amount1In
uint256 numberOfTimeIntervals
returns: uint256
mint 0x6a627842
address to
returns: uint256
permit 0xd505accf
address owner
address spender
uint256 value
uint256 deadline
uint8 v
bytes32 r
bytes32 s
skim 0xbc25cf77
address to
swap 0x022c0d9f
uint256 amount0Out
uint256 amount1Out
address to
bytes data
sync 0xfff6cae9
No parameters
togglePauseNewSwaps 0x96f29127
No parameters
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
withdrawProceedsFromLongTermSwap 0x81fd0a46
uint256 orderId
returns: bool, address, uint256

Recent Transactions

This address has 1 on-chain transactions, but only 0.8% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →