Address Contract Partially Verified
Address
0xcB0bC7C879bb3E9CFEB9d8EFef653F33B3d242e9
Balance
0 ETH
Nonce
1
Code Size
21920 bytes
Creator
0xB076b06F...Be4b at tx 0x6ad31727...e2fd50
Indexed Transactions
0 (1 on-chain, 0.8% indexed)
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 →