Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x2E703D658f8dd21709a7B458967aB4081F8D3d05
Balance 0 ETH
Nonce 1
Code Size 20125 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

20125 bytes
0x608060405234801561001057600080fd5b506004361061025e5760003560e01c80637e932d3211610146578063a9059cbb116100c3578063c92aecc411610087578063c92aecc4146113b6578063d828bb8814611400578063dd62ed3e14611456578063f11d2ff4146114ce578063f2fde38b1461152d578063f8bda7b9146115715761025e565b8063a9059cbb146111bf578063ba443d3314611225578063bbde3adc14611281578063c0046e3914611304578063c912ff7a146113725761025e565b8063919531891161010a5780639195318914610e3357806395d89b4114610f155780639667708614610f985780639d16b2c5146110bb578063a8e9d528146111515761025e565b80637e932d3214610c305780637ec8c85714610c605780638334278d14610cf9578063838e6a2214610d675780638da5cb5b14610de95761025e565b8063313ce567116101df578063525d0da7116101a3578063525d0da71461085b578063546e0c9b146108dd5780635ccd4afd146109d357806370a0823114610ab557806372b4129a14610b0d578063775d986514610ba35761025e565b8063313ce5671461059f5780633cae77f7146105c35780633cea3c89146106475780634737287d146106d157806351dbb2a7146107655761025e565b80630ceb9386116102265780630ceb93861461046957806318160ddd1461048b5780631a686502146104a957806323b872dd1461050f5780632a14b80a146105955761025e565b806301ffc9a714610263578063054f7d9c146102c857806306fdde03146102ea578063095ea7b31461036d5780630b2583c8146103d3575b600080fd5b6102ae6004803603602081101561027957600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690602001909291905050506115ab565b604051808215151515815260200191505060405180910390f35b6102d061169a565b604051808215151515815260200191505060405180910390f35b6102f26116ad565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610332578082015181840152602081019050610317565b50505050905090810190601f16801561035f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103b96004803603604081101561038357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506116e6565b604051808215151515815260200191505060405180910390f35b610453600480360360a08110156103e957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919050505061186f565b6040518082815260200191505060405180910390f35b610471611bb5565b604051808215151515815260200191505060405180910390f35b610493611bc8565b6040518082815260200191505060405180910390f35b6104b1611bd5565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156104fa5780820151818401526020810190506104df565b50505050905001935050505060405180910390f35b61057b6004803603606081101561052557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611d10565b604051808215151515815260200191505060405180910390f35b61059d611f74565b005b6105a7612146565b604051808260ff1660ff16815260200191505060405180910390f35b610605600480360360208110156105d957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061214b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106736004803603602081101561065d57600080fd5b81019080803590602001909291905050506121ba565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156106bc5780820151818401526020810190506106a1565b50505050905001935050505060405180910390f35b610707600480360360408110156106e757600080fd5b810190808035906020019092919080359060200190929190505050612364565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015610750578082015181840152602081019050610735565b50505050905001935050505060405180910390f35b6108456004803603608081101561077b57600080fd5b810190808035906020019064010000000081111561079857600080fd5b8201836020820111156107aa57600080fd5b803590602001918460208302840111640100000000831117156107cc57600080fd5b9091929391929390803590602001906401000000008111156107ed57600080fd5b8201836020820111156107ff57600080fd5b8035906020019184602083028401116401000000008311171561082157600080fd5b9091929391929390803590602001909291908035906020019092919050505061263f565b6040518082815260200191505060405180910390f35b6108c76004803603606081101561087157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506128e3565b6040518082815260200191505060405180910390f35b6109bd600480360360808110156108f357600080fd5b810190808035906020019064010000000081111561091057600080fd5b82018360208201111561092257600080fd5b8035906020019184602083028401116401000000008311171561094457600080fd5b90919293919293908035906020019064010000000081111561096557600080fd5b82018360208201111561097757600080fd5b8035906020019184602083028401116401000000008311171561099957600080fd5b90919293919293908035906020019092919080359060200190929190505050612a4f565b6040518082815260200191505060405180910390f35b610a9f600480360360408110156109e957600080fd5b8101908080359060200190640100000000811115610a0657600080fd5b820183602082011115610a1857600080fd5b80359060200191846020830284011164010000000083111715610a3a57600080fd5b909192939192939080359060200190640100000000811115610a5b57600080fd5b820183602082011115610a6d57600080fd5b80359060200191846020830284011164010000000083111715610a8f57600080fd5b9091929391929390505050612cf3565b6040518082815260200191505060405180910390f35b610af760048036036020811015610acb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612e5e565b6040518082815260200191505060405180910390f35b610b8d600480360360a0811015610b2357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050612eaa565b6040518082815260200191505060405180910390f35b610bd960048036036040811015610bb957600080fd5b8101908080359060200190929190803590602001909291905050506131f0565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610c1c578082015181840152602081019050610c01565b505050509050019250505060405180910390f35b610c5e60048036036020811015610c4657600080fd5b810190808035151590602001909291905050506134d9565b005b610ca260048036036020811015610c7657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506135f3565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610ce5578082015181840152602081019050610cca565b505050509050019250505060405180910390f35b610d2560048036036020811015610d0f57600080fd5b81019080803590602001909291905050506137e0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610dd360048036036060811015610d7d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061381c565b6040518082815260200191505060405180910390f35b610df1613988565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610eff60048036036040811015610e4957600080fd5b8101908080359060200190640100000000811115610e6657600080fd5b820183602082011115610e7857600080fd5b80359060200191846020830284011164010000000083111715610e9a57600080fd5b909192939192939080359060200190640100000000811115610ebb57600080fd5b820183602082011115610ecd57600080fd5b80359060200191846020830284011164010000000083111715610eef57600080fd5b90919293919293905050506139ad565b6040518082815260200191505060405180910390f35b610f1d613b18565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610f5d578082015181840152602081019050610f42565b50505050905090810190601f168015610f8a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61106460048036036040811015610fae57600080fd5b8101908080359060200190640100000000811115610fcb57600080fd5b820183602082011115610fdd57600080fd5b80359060200191846020830284011164010000000083111715610fff57600080fd5b90919293919293908035906020019064010000000081111561102057600080fd5b82018360208201111561103257600080fd5b8035906020019184602083028401116401000000008311171561105457600080fd5b9091929391929390505050613b51565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156110a757808201518184015260208101905061108c565b505050509050019250505060405180910390f35b61113b600480360360a08110156110d157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050613d7b565b6040518082815260200191505060405180910390f35b61117d6004803603602081101561116757600080fd5b81019080803590602001909291905050506141bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61120b600480360360408110156111d557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506141f7565b604051808215151515815260200191505060405180910390f35b6112676004803603602081101561123b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614426565b604051808215151515815260200191505060405180910390f35b6112ad6004803603602081101561129757600080fd5b8101908080359060200190929190505050614451565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156112f05780820151818401526020810190506112d5565b505050509050019250505060405180910390f35b6113306004803603602081101561131a57600080fd5b810190808035906020019092919050505061460a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6113b46004803603602081101561138857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614646565b005b6113be614969565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b611454600480360360a081101561141657600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919050505061497b565b005b6114b86004803603604081101561146c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614ad4565b6040518082815260200191505060405180910390f35b6114d6614b5e565b6040518087600f0b600f0b815260200186600f0b600f0b815260200185600f0b600f0b815260200184600f0b600f0b815260200183600f0b600f0b8152602001828152602001965050505050505060405180910390f35b61156f6004803603602081101561154357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614bc9565b005b611579614d49565b604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b6000817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166301ffc9a760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806116445750817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916637f5828d060e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806116935750817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166336372b0760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600e60019054906101000a900460ff1681565b6040518060400160405280600681526020017f5368656c6c73000000000000000000000000000000000000000000000000000081525081565b6000600e60029054906101000a900460ff1661176a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff02191690831515021790555073d1bd63adb712130524b96ea2984fcd6d1fad04196328709da7600185856040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060206040518083038186803b15801561181157600080fd5b505af4158015611825573d6000803e3d6000fd5b505050506040513d602081101561183b57600080fd5b810190808051906020019092919050505090506001600e60026101000a81548160ff02191690831515021790555092915050565b6000818042106118e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f5368656c6c2f74782d646561646c696e652d706173736564000000000000000081525060200191505060405180910390fd5b600e60019054906101000a900460ff161561194d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b600e60029054906101000a900460ff166119cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff021916908315150217905550735134d1c820fec6e9727d4496d6e102b9f64231f5633055a5a16001898989336040518663ffffffff1660e01b8152600401808681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019550505050505060206040518083038186803b158015611ade57600080fd5b505af4158015611af2573d6000803e3d6000fd5b505050506040513d6020811015611b0857600080fd5b81019080805190602001909291905050509150838211611b90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f5368656c6c2f62656c6f772d6d696e2d7461726765742d616d6f756e7400000081525060200191505060405180910390fd5b6001600e60026101000a81548160ff0219169083151502179055505095945050505050565b600e60009054906101000a900460ff1681565b6000600160040154905090565b600060607308e822f3cc5b0a60a2849588b79088766875d43a63449960ea60016040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015611c2957600080fd5b505af4158015611c3d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506040811015611c6757600080fd5b810190808051906020019092919080516040519392919084640100000000821115611c9157600080fd5b83820191506020820185811115611ca757600080fd5b8251866020820283011164010000000082111715611cc457600080fd5b8083526020830192505050908051906020019060200280838360005b83811015611cfb578082015181840152602081019050611ce0565b50505050905001604052505050915091509091565b6000600e60029054906101000a900460ff16611d94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff021916908315150217905550600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff1615611e55576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180614e466023913960400191505060405180910390fd5b73d1bd63adb712130524b96ea2984fcd6d1fad041963de3fe89f60018686866040518563ffffffff1660e01b8152600401808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060206040518083038186803b158015611f1557600080fd5b505af4158015611f29573d6000803e3d6000fd5b505050506040513d6020811015611f3f57600080fd5b810190808051906020019092919050505090506001600e60026101000a81548160ff0219169083151502179055509392505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612036576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f5368656c6c2f63616c6c65722d69732d6e6f742d6f776e65720000000000000081525060200191505060405180910390fd5b600e60019054906101000a900460ff166120b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5368656c6c2f6d7573742d62652d66726f7a656e00000000000000000000000081525060200191505060405180910390fd5b732baf1ddd7fdde8ffe15a1911cb032851a8614bf3637c6d404b6001600a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561211157600080fd5b505af4158015612125573d6000803e3d6000fd5b505050506001600e60006101000a81548160ff021916908315150217905550565b601281565b6000600160060160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006060600e60019054906101000a900460ff1615612224576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b738dec04e31c6ef645cbb43586f7f0895537d2dfb363b47b942b6001856040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561227c57600080fd5b505af4158015612290573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060408110156122ba57600080fd5b8101908080519060200190929190805160405193929190846401000000008211156122e457600080fd5b838201915060208201858111156122fa57600080fd5b825186602082028301116401000000008211171561231757600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561234e578082015181840152602081019050612333565b5050505090500160405250505091509150915091565b60006060828042106123de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f5368656c6c2f74782d646561646c696e652d706173736564000000000000000081525060200191505060405180910390fd5b600e60019054906101000a900460ff1615612444576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b600e60029054906101000a900460ff166124c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff021916908315150217905550738dec04e31c6ef645cbb43586f7f0895537d2dfb3633da940356001876040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561253957600080fd5b505af415801561254d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250604081101561257757600080fd5b8101908080519060200190929190805160405193929190846401000000008211156125a157600080fd5b838201915060208201858111156125b757600080fd5b82518660208202830111640100000000821117156125d457600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561260b5780820151818401526020810190506125f0565b50505050905001604052505050925092506001600e60026101000a81548160ff021916908315150217905550509250929050565b6000818042106126b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f5368656c6c2f74782d646561646c696e652d706173736564000000000000000081525060200191505060405180910390fd5b600e60019054906101000a900460ff161561271d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b600e60029054906101000a900460ff1661279f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff021916908315150217905550732b9b938d934266e185ecd329b145072aab6db5f1639bbfcd6d60018a8a8a8a8a6040518763ffffffff1660e01b81526004018087815260200180602001806020018481526020018381038352888882818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252868682818152602001925060200280828437600081840152601f19601f8201169050808301925050509850505050505050505060206040518083038186803b15801561288057600080fd5b505af4158015612894573d6000803e3d6000fd5b505050506040513d60208110156128aa57600080fd5b810190808051906020019092919050505091506001600e60026101000a81548160ff021916908315150217905550509695505050505050565b6000600e60019054906101000a900460ff161561294b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b735134d1c820fec6e9727d4496d6e102b9f64231f563e4499c4660018686866040518563ffffffff1660e01b8152600401808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060206040518083038186803b158015612a0b57600080fd5b505af4158015612a1f573d6000803e3d6000fd5b505050506040513d6020811015612a3557600080fd5b810190808051906020019092919050505090509392505050565b600081804210612ac7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f5368656c6c2f74782d646561646c696e652d706173736564000000000000000081525060200191505060405180910390fd5b600e60019054906101000a900460ff1615612b2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b600e60029054906101000a900460ff16612baf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff021916908315150217905550732b9b938d934266e185ecd329b145072aab6db5f1632454e63d60018a8a8a8a8a6040518763ffffffff1660e01b81526004018087815260200180602001806020018481526020018381038352888882818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252868682818152602001925060200280828437600081840152601f19601f8201169050808301925050509850505050505050505060206040518083038186803b158015612c9057600080fd5b505af4158015612ca4573d6000803e3d6000fd5b505050506040513d6020811015612cba57600080fd5b810190808051906020019092919050505091506001600e60026101000a81548160ff021916908315150217905550509695505050505050565b6000600e60019054906101000a900460ff1615612d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b732b9b938d934266e185ecd329b145072aab6db5f163f38062256001878787876040518663ffffffff1660e01b81526004018086815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f82011690508083019250505097505050505050505060206040518083038186803b158015612e1957600080fd5b505af4158015612e2d573d6000803e3d6000fd5b505050506040513d6020811015612e4357600080fd5b81019080805190602001909291905050509050949350505050565b6000600160070160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600081804210612f22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f5368656c6c2f74782d646561646c696e652d706173736564000000000000000081525060200191505060405180910390fd5b600e60019054906101000a900460ff1615612f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b600e60029054906101000a900460ff1661300a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff021916908315150217905550735134d1c820fec6e9727d4496d6e102b9f64231f5638bd855b46001898988336040518663ffffffff1660e01b8152600401808681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019550505050505060206040518083038186803b15801561311957600080fd5b505af415801561312d573d6000803e3d6000fd5b505050506040513d602081101561314357600080fd5b810190808051906020019092919050505091508482106131cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f5368656c6c2f61626f76652d6d61782d6f726967696e2d616d6f756e7400000081525060200191505060405180910390fd5b6001600e60026101000a81548160ff0219169083151502179055505095945050505050565b606081804210613268576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f5368656c6c2f74782d646561646c696e652d706173736564000000000000000081525060200191505060405180910390fd5b600e60009054906101000a900460ff16156132eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f5368656c6c2f706f6f6c2d706172746974696f6e65640000000000000000000081525060200191505060405180910390fd5b600e60029054906101000a900460ff1661336d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff021916908315150217905550738dec04e31c6ef645cbb43586f7f0895537d2dfb363a48b9c636001866040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156133e057600080fd5b505af41580156133f4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561341e57600080fd5b810190808051604051939291908464010000000082111561343e57600080fd5b8382019150602082018581111561345457600080fd5b825186602082028301116401000000008211171561347157600080fd5b8083526020830192505050908051906020019060200280838360005b838110156134a857808201518184015260208101905061348d565b5050505090500160405250505091506001600e60026101000a81548160ff0219169083151502179055505092915050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461359b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f5368656c6c2f63616c6c65722d69732d6e6f742d6f776e65720000000000000081525060200191505060405180910390fd5b7f7c029deaca9b6c66abb68e5f874a812822f0fcaa52a890f980a7ab1afb5edba681604051808215151515815260200191505060405180910390a180600e60016101000a81548160ff02191690831515021790555050565b6060600e60009054906101000a900460ff16613677576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f5368656c6c2f706f6f6c2d6e6f742d706172746974696f6e656400000000000081525060200191505060405180910390fd5b732baf1ddd7fdde8ffe15a1911cb032851a8614bf363845e86526001600a856040518463ffffffff1660e01b8152600401808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060006040518083038186803b15801561370457600080fd5b505af4158015613718573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561374257600080fd5b810190808051604051939291908464010000000082111561376257600080fd5b8382019150602082018581111561377857600080fd5b825186602082028301116401000000008211171561379557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156137cc5780820151818401526020810190506137b1565b505050509050016040525050509050919050565b600d81815481106137ed57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600e60019054906101000a900460ff1615613884576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b735134d1c820fec6e9727d4496d6e102b9f64231f5631c9f0d7760018686866040518563ffffffff1660e01b8152600401808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060206040518083038186803b15801561394457600080fd5b505af4158015613958573d6000803e3d6000fd5b505050506040513d602081101561396e57600080fd5b810190808051906020019092919050505090509392505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600e60019054906101000a900460ff1615613a15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b732b9b938d934266e185ecd329b145072aab6db5f163988060936001878787876040518663ffffffff1660e01b81526004018086815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f82011690508083019250505097505050505050505060206040518083038186803b158015613ad357600080fd5b505af4158015613ae7573d6000803e3d6000fd5b505050506040513d6020811015613afd57600080fd5b81019080805190602001909291905050509050949350505050565b6040518060400160405280600381526020017f53484c000000000000000000000000000000000000000000000000000000000081525081565b6060600e60009054906101000a900460ff16613bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f5368656c6c2f706f6f6c2d6e6f742d706172746974696f6e656400000000000081525060200191505060405180910390fd5b732baf1ddd7fdde8ffe15a1911cb032851a8614bf363e407bd146001600a888888886040518763ffffffff1660e01b81526004018087815260200186815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509850505050505050505060006040518083038186803b158015613c9c57600080fd5b505af4158015613cb0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506020811015613cda57600080fd5b8101908080516040519392919084640100000000821115613cfa57600080fd5b83820191506020820185811115613d1057600080fd5b8251866020820283011164010000000082111715613d2d57600080fd5b8083526020830192505050908051906020019060200280838360005b83811015613d64578082015181840152602081019050613d49565b505050509050016040525050509050949350505050565b600081804210613df3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f5368656c6c2f74782d646561646c696e652d706173736564000000000000000081525060200191505060405180910390fd5b600e60019054906101000a900460ff1615613e59576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180614e166030913960400191505060405180910390fd5b600e60029054906101000a900460ff16613edb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff02191690831515021790555060005a9050735134d1c820fec6e9727d4496d6e102b9f64231f5633055a5a160018a8a8a336040518663ffffffff1660e01b8152600401808681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019550505050505060206040518083038186803b158015613fef57600080fd5b505af4158015614003573d6000803e3d6000fd5b505050506040513d602081101561401957600080fd5b810190808051906020019092919050505092508483116140a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f5368656c6c2f62656c6f772d6d696e2d7461726765742d616d6f756e7400000081525060200191505060405180910390fd5b6000803690506010025a8361520801030190506d4946c0e9f43f4dee607b0ef1fa1c73ffffffffffffffffffffffffffffffffffffffff1663079d229f3361a0aa61374a8501816140ee57fe5b046040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561415857600080fd5b505af115801561416c573d6000803e3d6000fd5b505050506040513d602081101561418257600080fd5b81019080805190602001909291905050505050506001600e60026101000a81548160ff0219169083151502179055505095945050505050565b600c81815481106141c857fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600e60029054906101000a900460ff1661427b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5368656c6c2f72652d656e74657265640000000000000000000000000000000081525060200191505060405180910390fd5b6000600e60026101000a81548160ff021916908315150217905550600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff161561433c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180614e466023913960400191505060405180910390fd5b73d1bd63adb712130524b96ea2984fcd6d1fad041963d0066eb2600185856040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060206040518083038186803b1580156143c857600080fd5b505af41580156143dc573d6000803e3d6000fd5b505050506040513d60208110156143f257600080fd5b810190808051906020019092919050505090506001600e60026101000a81548160ff02191690831515021790555092915050565b600a6020528060005260406000206000915090508060010160009054906101000a900460ff16905081565b6060600e60009054906101000a900460ff16156144d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f5368656c6c2f706f6f6c2d706172746974696f6e65640000000000000000000081525060200191505060405180910390fd5b738dec04e31c6ef645cbb43586f7f0895537d2dfb36318e581fa6001846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561452e57600080fd5b505af4158015614542573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561456c57600080fd5b810190808051604051939291908464010000000082111561458c57600080fd5b838201915060208201858111156145a257600080fd5b82518660208202830111640100000000821117156145bf57600080fd5b8083526020830192505050908051906020019060200280838360005b838110156145f65780820151818401526020810190506145db565b505050509050016040525050509050919050565b600b818154811061461757fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614708576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f5368656c6c2f63616c6c65722d69732d6e6f742d6f776e65720000000000000081525060200191505060405180910390fd5b6000600c80549050905060008090505b600c805490508110156148e457600c818154811061473257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156147fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f5368656c6c2f63616e6e6f742d64656c6574652d6e756d65726169726500000081525060200191505060405180910390fd5b600d818154811061480b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156148d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f5368656c6c2f63616e6e6f742d64656c6574652d72657365727665000000000081525060200191505060405180910390fd5b8080600101915050614718565b50600160060160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549060ff021916905550505050565b6d4946c0e9f43f4dee607b0ef1fa1c81565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614a3d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f5368656c6c2f63616c6c65722d69732d6e6f742d6f776e65720000000000000081525060200191505060405180910390fd5b73be1e6ef049b15bc77bb796babecbeea2707770d76364542e7d600187878787876040518763ffffffff1660e01b815260040180878152602001868152602001858152602001848152602001838152602001828152602001965050505050505060006040518083038186803b158015614ab557600080fd5b505af4158015614ac9573d6000803e3d6000fd5b505050505050505050565b6000600160080160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60018060000160009054906101000a9004600f0b908060000160109054906101000a9004600f0b908060010160009054906101000a9004600f0b908060010160109054906101000a9004600f0b908060020160009054906101000a9004600f0b908060040154905086565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614c8b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f5368656c6c2f63616c6c65722d69732d6e6f742d6f776e65720000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f0d18b5fd22306e373229b9439188228edca81207d1667f604daf6cef8aa3ee6760405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080600080600073be1e6ef049b15bc77bb796babecbeea2707770d76375eccc3660016040518263ffffffff1660e01b81526004018082815260200191505060a06040518083038186803b158015614da157600080fd5b505af4158015614db5573d6000803e3d6000fd5b505050506040513d60a0811015614dcb57600080fd5b81019080805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919050505094509450945094509450909192939456fe5368656c6c2f66726f7a656e2d6f6e6c792d616c6c6f77696e672d70726f706f7274696f6e616c2d77697468647261775368656c6c2f6e6f2d7472616e73666572732d6f6e63652d706172746974696f6e6564a265627a7a72315820f769be366fcee1ed1b834cecf85782f34545df754bd835ec38c95496836d9ef364736f6c634300050f0032

Verified Source Code Partial Match

Compiler: v0.5.15+commit.6a57276f EVM: istanbul Optimization: No
Shell.sol 3532 lines
/**
 *Submitted for verification at Etherscan.io on 2020-09-25
*/

// hevm: flattened sources of src/ShellFactory.sol
pragma solidity >0.4.13 >=0.4.23 >=0.5.0 <0.6.0 >=0.5.7 <0.6.0;

////// lib/abdk-libraries-solidity/src/ABDKMath64x64.sol
/*
 * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.
 * Author: Mikhail Vladimirov <[email protected]>
 */
/* pragma solidity ^0.5.7; */

/**
 * Smart contract library of mathematical functions operating with signed
 * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is
 * basically a simple fraction whose numerator is signed 128-bit integer and
 * denominator is 2^64.  As long as denominator is always the same, there is no
 * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are
 * represented by int128 type holding only the numerator.
 */
library ABDKMath64x64 {
  /**
   * Minimum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;

  /**
   * Maximum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

  /**
   * Convert signed 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromInt (int256 x) internal pure returns (int128) {
    require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
    return int128 (x << 64);
  }

  /**
   * Convert signed 64.64 fixed point number into signed 64-bit integer number
   * rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64-bit integer number
   */
  function toInt (int128 x) internal pure returns (int64) {
    return int64 (x >> 64);
  }

  /**
   * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromUInt (uint256 x) internal pure returns (int128) {
    require (x <= 0x7FFFFFFFFFFFFFFF);
    return int128 (x << 64);
  }

  /**
   * Convert signed 64.64 fixed point number into unsigned 64-bit integer
   * number rounding down.  Revert on underflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return unsigned 64-bit integer number
   */
  function toUInt (int128 x) internal pure returns (uint64) {
    require (x >= 0);
    return uint64 (x >> 64);
  }

  /**
   * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point
   * number rounding down.  Revert on overflow.
   *
   * @param x signed 128.128-bin fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function from128x128 (int256 x) internal pure returns (int128) {
    int256 result = x >> 64;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Convert signed 64.64 fixed point number into signed 128.128 fixed point
   * number.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 128.128 fixed point number
   */
  function to128x128 (int128 x) internal pure returns (int256) {
    return int256 (x) << 64;
  }

  /**
   * Calculate x + y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function add (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) + y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate x - y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sub (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) - y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate x * y rounding down.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function mul (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) * y >> 64;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point
   * number and y is signed 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y signed 256-bit integer number
   * @return signed 256-bit integer number
   */
  function muli (int128 x, int256 y) internal pure returns (int256) {
    if (x == MIN_64x64) {
      require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
        y <= 0x1000000000000000000000000000000000000000000000000);
      return -y << 63;
    } else {
      bool negativeResult = false;
      if (x < 0) {
        x = -x;
        negativeResult = true;
      }
      if (y < 0) {
        y = -y; // We rely on overflow behavior here
        negativeResult = !negativeResult;
      }
      uint256 absoluteResult = mulu (x, uint256 (y));
      if (negativeResult) {
        require (absoluteResult <=
          0x8000000000000000000000000000000000000000000000000000000000000000);
        return -int256 (absoluteResult); // We rely on overflow behavior here
      } else {
        require (absoluteResult <=
          0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
        return int256 (absoluteResult);
      }
    }
  }

  /**
   * Calculate x * y rounding down, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y unsigned 256-bit integer number
   * @return unsigned 256-bit integer number
   */
  function mulu (int128 x, uint256 y) internal pure returns (uint256) {
    if (y == 0) return 0;

    require (x >= 0);

    uint256 lo = (uint256 (x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
    uint256 hi = uint256 (x) * (y >> 128);

    require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
    hi <<= 64;

    require (hi <=
      0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
    return hi + lo;
  }

  /**
   * Calculate x / y rounding towards zero.  Revert on overflow or when y is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function div (int128 x, int128 y) internal pure returns (int128) {
    require (y != 0);
    int256 result = (int256 (x) << 64) / y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are signed 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x signed 256-bit integer number
   * @param y signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divi (int256 x, int256 y) internal pure returns (int128) {
    require (y != 0);

    bool negativeResult = false;
    if (x < 0) {
      x = -x; // We rely on overflow behavior here
      negativeResult = true;
    }
    if (y < 0) {
      y = -y; // We rely on overflow behavior here
      negativeResult = !negativeResult;
    }
    uint128 absoluteResult = divuu (uint256 (x), uint256 (y));
    if (negativeResult) {
      require (absoluteResult <= 0x80000000000000000000000000000000);
      return -int128 (absoluteResult); // We rely on overflow behavior here
    } else {
      require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int128 (absoluteResult); // We rely on overflow behavior here
    }
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divu (uint256 x, uint256 y) internal pure returns (int128) {
    require (y != 0);
    uint128 result = divuu (x, y);
    require (result <= uint128 (MAX_64x64));
    return int128 (result);
  }

  /**
   * Calculate -x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function neg (int128 x) internal pure returns (int128) {
    require (x != MIN_64x64);
    return -x;
  }

  /**
   * Calculate |x|.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function abs (int128 x) internal pure returns (int128) {
    require (x != MIN_64x64);
    return x < 0 ? -x : x;
  }

  /**
   * Calculate 1 / x rounding towards zero.  Revert on overflow or when x is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function inv (int128 x) internal pure returns (int128) {
    require (x != 0);
    int256 result = int256 (0x100000000000000000000000000000000) / x;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function avg (int128 x, int128 y) internal pure returns (int128) {
    return int128 ((int256 (x) + int256 (y)) >> 1);
  }

  /**
   * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down.
   * Revert on overflow or in case x * y is negative.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function gavg (int128 x, int128 y) internal pure returns (int128) {
    int256 m = int256 (x) * int256 (y);
    require (m >= 0);
    require (m <
        0x4000000000000000000000000000000000000000000000000000000000000000);
    return int128 (sqrtu (uint256 (m), uint256 (x) + uint256 (y) >> 1));
  }

  /**
   * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y uint256 value
   * @return signed 64.64-bit fixed point number
   */
  function pow (int128 x, uint256 y) internal pure returns (int128) {
    uint256 absoluteResult;
    bool negativeResult = false;
    if (x >= 0) {
      absoluteResult = powu (uint256 (x) << 63, y);
    } else {
      // We rely on overflow behavior here
      absoluteResult = powu (uint256 (uint128 (-x)) << 63, y);
      negativeResult = y & 1 > 0;
    }

    absoluteResult >>= 63;

    if (negativeResult) {
      require (absoluteResult <= 0x80000000000000000000000000000000);
      return -int128 (absoluteResult); // We rely on overflow behavior here
    } else {
      require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int128 (absoluteResult); // We rely on overflow behavior here
    }
  }

  /**
   * Calculate sqrt (x) rounding down.  Revert if x < 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sqrt (int128 x) internal pure returns (int128) {
    require (x >= 0);
    return int128 (sqrtu (uint256 (x) << 64, 0x10000000000000000));
  }

  /**
   * Calculate binary logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function log_2 (int128 x) internal pure returns (int128) {
    require (x > 0);

    int256 msb = 0;
    int256 xc = x;
    if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
    if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
    if (xc >= 0x10000) { xc >>= 16; msb += 16; }
    if (xc >= 0x100) { xc >>= 8; msb += 8; }
    if (xc >= 0x10) { xc >>= 4; msb += 4; }
    if (xc >= 0x4) { xc >>= 2; msb += 2; }
    if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

    int256 result = msb - 64 << 64;
    uint256 ux = uint256 (x) << 127 - msb;
    for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
      ux *= ux;
      uint256 b = ux >> 255;
      ux >>= 127 + b;
      result += bit * int256 (b);
    }

    return int128 (result);
  }

  /**
   * Calculate natural logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function ln (int128 x) internal pure returns (int128) {
    require (x > 0);

    return int128 (
        uint256 (log_2 (x)) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128);
  }

  /**
   * Calculate binary exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp_2 (int128 x) internal pure returns (int128) {
    require (x < 0x400000000000000000); // Overflow

    if (x < -0x400000000000000000) return 0; // Underflow

    uint256 result = 0x80000000000000000000000000000000;

    if (x & 0x8000000000000000 > 0)
      result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
    if (x & 0x4000000000000000 > 0)
      result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
    if (x & 0x2000000000000000 > 0)
      result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
    if (x & 0x1000000000000000 > 0)
      result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
    if (x & 0x800000000000000 > 0)
      result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
    if (x & 0x400000000000000 > 0)
      result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
    if (x & 0x200000000000000 > 0)
      result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
    if (x & 0x100000000000000 > 0)
      result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
    if (x & 0x80000000000000 > 0)
      result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
    if (x & 0x40000000000000 > 0)
      result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
    if (x & 0x20000000000000 > 0)
      result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
    if (x & 0x10000000000000 > 0)
      result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
    if (x & 0x8000000000000 > 0)
      result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
    if (x & 0x4000000000000 > 0)
      result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
    if (x & 0x2000000000000 > 0)
      result = result * 0x1000162E525EE054754457D5995292026 >> 128;
    if (x & 0x1000000000000 > 0)
      result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
    if (x & 0x800000000000 > 0)
      result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
    if (x & 0x400000000000 > 0)
      result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
    if (x & 0x200000000000 > 0)
      result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
    if (x & 0x100000000000 > 0)
      result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
    if (x & 0x80000000000 > 0)
      result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
    if (x & 0x40000000000 > 0)
      result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
    if (x & 0x20000000000 > 0)
      result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
    if (x & 0x10000000000 > 0)
      result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
    if (x & 0x8000000000 > 0)
      result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
    if (x & 0x4000000000 > 0)
      result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
    if (x & 0x2000000000 > 0)
      result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
    if (x & 0x1000000000 > 0)
      result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
    if (x & 0x800000000 > 0)
      result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
    if (x & 0x400000000 > 0)
      result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
    if (x & 0x200000000 > 0)
      result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
    if (x & 0x100000000 > 0)
      result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
    if (x & 0x80000000 > 0)
      result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
    if (x & 0x40000000 > 0)
      result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
    if (x & 0x20000000 > 0)
      result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
    if (x & 0x10000000 > 0)
      result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
    if (x & 0x8000000 > 0)
      result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
    if (x & 0x4000000 > 0)
      result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
    if (x & 0x2000000 > 0)
      result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
    if (x & 0x1000000 > 0)
      result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
    if (x & 0x800000 > 0)
      result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
    if (x & 0x400000 > 0)
      result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
    if (x & 0x200000 > 0)
      result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
    if (x & 0x100000 > 0)
      result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
    if (x & 0x80000 > 0)
      result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
    if (x & 0x40000 > 0)
      result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
    if (x & 0x20000 > 0)
      result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
    if (x & 0x10000 > 0)
      result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
    if (x & 0x8000 > 0)
      result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
    if (x & 0x4000 > 0)
      result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
    if (x & 0x2000 > 0)
      result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
    if (x & 0x1000 > 0)
      result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
    if (x & 0x800 > 0)
      result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
    if (x & 0x400 > 0)
      result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
    if (x & 0x200 > 0)
      result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
    if (x & 0x100 > 0)
      result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
    if (x & 0x80 > 0)
      result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
    if (x & 0x40 > 0)
      result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
    if (x & 0x20 > 0)
      result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
    if (x & 0x10 > 0)
      result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
    if (x & 0x8 > 0)
      result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
    if (x & 0x4 > 0)
      result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
    if (x & 0x2 > 0)
      result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
    if (x & 0x1 > 0)
      result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;

    result >>= 63 - (x >> 64);
    require (result <= uint256 (MAX_64x64));

    return int128 (result);
  }

  /**
   * Calculate natural exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp (int128 x) internal pure returns (int128) {
    require (x < 0x400000000000000000); // Overflow

    if (x < -0x400000000000000000) return 0; // Underflow

    return exp_2 (
        int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return unsigned 64.64-bit fixed point number
   */
  function divuu (uint256 x, uint256 y) private pure returns (uint128) {
    require (y != 0);

    uint256 result;

    if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
      result = (x << 64) / y;
    else {
      uint256 msb = 192;
      uint256 xc = x >> 192;
      if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
      if (xc >= 0x10000) { xc >>= 16; msb += 16; }
      if (xc >= 0x100) { xc >>= 8; msb += 8; }
      if (xc >= 0x10) { xc >>= 4; msb += 4; }
      if (xc >= 0x4) { xc >>= 2; msb += 2; }
      if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

      result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
      require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

      uint256 hi = result * (y >> 128);
      uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

      uint256 xh = x >> 192;
      uint256 xl = x << 64;

      if (xl < lo) xh -= 1;
      xl -= lo; // We rely on overflow behavior here
      lo = hi << 128;
      if (xl < lo) xh -= 1;
      xl -= lo; // We rely on overflow behavior here

      assert (xh == hi >> 128);

      result += xl / y;
    }

    require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
    return uint128 (result);
  }

  /**
   * Calculate x^y assuming 0^0 is 1, where x is unsigned 129.127 fixed point
   * number and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x unsigned 129.127-bit fixed point number
   * @param y uint256 value
   * @return unsigned 129.127-bit fixed point number
   */
  function powu (uint256 x, uint256 y) private pure returns (uint256) {
    if (y == 0) return 0x80000000000000000000000000000000;
    else if (x == 0) return 0;
    else {
      int256 msb = 0;
      uint256 xc = x;
      if (xc >= 0x100000000000000000000000000000000) { xc >>= 128; msb += 128; }
      if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
      if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
      if (xc >= 0x10000) { xc >>= 16; msb += 16; }
      if (xc >= 0x100) { xc >>= 8; msb += 8; }
      if (xc >= 0x10) { xc >>= 4; msb += 4; }
      if (xc >= 0x4) { xc >>= 2; msb += 2; }
      if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

      int256 xe = msb - 127;
      if (xe > 0) x >>= xe;
      else x <<= -xe;

      uint256 result = 0x80000000000000000000000000000000;
      int256 re = 0;

      while (y > 0) {
        if (y & 1 > 0) {
          result = result * x;
          y -= 1;
          re += xe;
          if (result >=
            0x8000000000000000000000000000000000000000000000000000000000000000) {
            result >>= 128;
            re += 1;
          } else result >>= 127;
          if (re < -127) return 0; // Underflow
          require (re < 128); // Overflow
        } else {
          x = x * x;
          y >>= 1;
          xe <<= 1;
          if (x >=
            0x8000000000000000000000000000000000000000000000000000000000000000) {
            x >>= 128;
            xe += 1;
          } else x >>= 127;
          if (xe < -127) return 0; // Underflow
          require (xe < 128); // Overflow
        }
      }

      if (re > 0) result <<= re;
      else if (re < 0) result >>= -re;

      return result;
    }
  }

  /**
   * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer
   * number.
   *
   * @param x unsigned 256-bit integer number
   * @return unsigned 128-bit integer number
   */
  function sqrtu (uint256 x, uint256 r) private pure returns (uint128) {
    if (x == 0) return 0;
    else {
      require (r > 0);
      while (true) {
        uint256 rr = x / r;
        if (r == rr || r + 1 == rr) return uint128 (r);
        else if (r == rr + 1) return uint128 (rr);
        r = r + rr + 1 >> 1;
      }
    }
  }
}

////// src/interfaces/IAssimilator.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/* pragma solidity ^0.5.0; */

interface IAssimilator {
    function intakeRaw (uint256 amount) external returns (int128);
    function intakeRawAndGetBalance (uint256 amount) external returns (int128, int128);
    function intakeNumeraire (int128 amount) external returns (uint256);
    function outputRaw (address dst, uint256 amount) external returns (int128);
    function outputRawAndGetBalance (address dst, uint256 amount) external returns (int128, int128);
    function outputNumeraire (address dst, int128 amount) external returns (uint256);
    function viewRawAmount (int128) external view returns (uint256);
    function viewNumeraireAmount (uint256) external view returns (int128);
    function viewNumeraireBalance (address) external view returns (int128);
    function viewNumeraireAmountAndBalance (address, uint256) external view returns (int128, int128);
}
////// src/Assimilators.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/* pragma solidity ^0.5.0; */

/* import "./interfaces/IAssimilator.sol"; */
/* import "abdk-libraries-solidity/ABDKMath64x64.sol"; */

library Assimilators {

    using ABDKMath64x64 for int128;
    IAssimilator constant iAsmltr = IAssimilator(address(0));

    function delegate(address _callee, bytes memory _data) internal returns (bytes memory) {

        (bool _success, bytes memory returnData_) = _callee.delegatecall(_data);

        assembly { if eq(_success, 0) { revert(add(returnData_, 0x20), returndatasize()) } }

        return returnData_;

    }

    function viewRawAmount (address _assim, int128 _amt) internal view returns (uint256 amount_) {

        amount_ = IAssimilator(_assim).viewRawAmount(_amt);

    }

    function viewNumeraireAmount (address _assim, uint256 _amt) internal view returns (int128 amt_) {

        amt_ = IAssimilator(_assim).viewNumeraireAmount(_amt);

    }

    function viewNumeraireAmountAndBalance (address _assim, uint256 _amt) internal view returns (int128 amt_, int128 bal_) {

        ( amt_, bal_ ) = IAssimilator(_assim).viewNumeraireAmountAndBalance(address(this), _amt);

    }

    function viewNumeraireBalance (address _assim) internal view returns (int128 bal_) {

        bal_ = IAssimilator(_assim).viewNumeraireBalance(address(this));

    }

    function intakeRaw (address _assim, uint256 _amt) internal returns (int128 amt_) {

        bytes memory data = abi.encodeWithSelector(iAsmltr.intakeRaw.selector, _amt);

        amt_ = abi.decode(delegate(_assim, data), (int128));

    }

    function intakeRawAndGetBalance (address _assim, uint256 _amt) internal returns (int128 amt_, int128 bal_) {

        bytes memory data = abi.encodeWithSelector(iAsmltr.intakeRawAndGetBalance.selector, _amt);

        ( amt_, bal_ ) = abi.decode(delegate(_assim, data), (int128,int128));

    }

    function intakeNumeraire (address _assim, int128 _amt) internal returns (uint256 amt_) {

        bytes memory data = abi.encodeWithSelector(iAsmltr.intakeNumeraire.selector, _amt);

        amt_ = abi.decode(delegate(_assim, data), (uint256));

    }

    function outputRaw (address _assim, address _dst, uint256 _amt) internal returns (int128 amt_ ) {

        bytes memory data = abi.encodeWithSelector(iAsmltr.outputRaw.selector, _dst, _amt);

        amt_ = abi.decode(delegate(_assim, data), (int128));

        amt_ = amt_.neg();

    }

    function outputRawAndGetBalance (address _assim, address _dst, uint256 _amt) internal returns (int128 amt_, int128 bal_) {

        bytes memory data = abi.encodeWithSelector(iAsmltr.outputRawAndGetBalance.selector, _dst, _amt);

        ( amt_, bal_ ) = abi.decode(delegate(_assim, data), (int128,int128));

        amt_ = amt_.neg();

    }

    function outputNumeraire (address _assim, address _dst, int128 _amt) internal returns (uint256 amt_) {

        bytes memory data = abi.encodeWithSelector(iAsmltr.outputNumeraire.selector, _dst, _amt.abs());

        amt_ = abi.decode(delegate(_assim, data), (uint256));

    }

}
////// src/UnsafeMath64x64.sol
/* pragma solidity ^0.5.0; */

library UnsafeMath64x64 {

  /**
   * Calculate x * y rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */

  function us_mul (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) * y >> 64;
    return int128 (result);
  }

  /**
   * Calculate x / y rounding towards zero.  Revert on overflow or when y is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */

  function us_div (int128 x, int128 y) internal pure returns (int128) {
    int256 result = (int256 (x) << 64) / y;
    return int128 (result);
  }

}

////// src/PartitionedLiquidity.sol
/* pragma solidity ^0.5.0; */

/* import "./Assimilators.sol"; */

/* import "./ShellStorage.sol"; */

/* import "./UnsafeMath64x64.sol"; */

library PartitionedLiquidity {

    using ABDKMath64x64 for uint;
    using ABDKMath64x64 for int128;
    using UnsafeMath64x64 for int128;

    event PoolPartitioned(bool);

    event PartitionRedeemed(address indexed token, address indexed redeemer, uint value);

    int128 constant ONE = 0x10000000000000000;

    function partition (
        ShellStorage.Shell storage shell,
        mapping (address => ShellStorage.PartitionTicket) storage partitionTickets
    ) external {

        uint _length = shell.assets.length;

        ShellStorage.PartitionTicket storage totalSupplyTicket = partitionTickets[address(this)];

        totalSupplyTicket.initialized = true;

        for (uint i = 0; i < _length; i++) totalSupplyTicket.claims.push(shell.totalSupply);

        emit PoolPartitioned(true);

    }

    function viewPartitionClaims (
        ShellStorage.Shell storage shell,
        mapping (address => ShellStorage.PartitionTicket) storage partitionTickets,
        address _addr
    ) external view returns (
        uint[] memory claims_
    ) {

        ShellStorage.PartitionTicket storage ticket = partitionTickets[_addr];

        if (ticket.initialized) return ticket.claims;

        uint _length = shell.assets.length;
        uint[] memory claims_ = new uint[](_length);
        uint _balance = shell.balances[msg.sender];

        for (uint i = 0; i < _length; i++) claims_[i] = _balance;

        return claims_;

    }

    function partitionedWithdraw (
        ShellStorage.Shell storage shell,
        mapping (address => ShellStorage.PartitionTicket) storage partitionTickets,
        address[] calldata _derivatives,
        uint[] calldata _withdrawals
    ) external returns (
        uint[] memory
    ) {

        uint _length = shell.assets.length;
        uint _balance = shell.balances[msg.sender];

        ShellStorage.PartitionTicket storage totalSuppliesTicket = partitionTickets[address(this)];
        ShellStorage.PartitionTicket storage ticket = partitionTickets[msg.sender];

        if (!ticket.initialized) {

            for (uint i = 0; i < _length; i++) ticket.claims.push(_balance);
            ticket.initialized = true;

        }

        _length = _derivatives.length;

        uint[] memory withdrawals_ = new uint[](_length);

        for (uint i = 0; i < _length; i++) {

            ShellStorage.Assimilator memory _assim = shell.assimilators[_derivatives[i]];

            require(totalSuppliesTicket.claims[_assim.ix] >= _withdrawals[i], "Shell/burn-exceeds-total-supply");
            
            require(ticket.claims[_assim.ix] >= _withdrawals[i], "Shell/insufficient-balance");

            require(_assim.addr != address(0), "Shell/unsupported-asset");

            int128 _reserveBalance = Assimilators.viewNumeraireBalance(_assim.addr);

            int128 _multiplier = _withdrawals[i].divu(1e18)
                .div(totalSuppliesTicket.claims[_assim.ix].divu(1e18));

            totalSuppliesTicket.claims[_assim.ix] = totalSuppliesTicket.claims[_assim.ix] - _withdrawals[i];

            ticket.claims[_assim.ix] = ticket.claims[_assim.ix] - _withdrawals[i];

            uint _withdrawal = Assimilators.outputNumeraire(
                _assim.addr,
                msg.sender,
                _reserveBalance.mul(_multiplier)
            );

            withdrawals_[i] = _withdrawal;

            emit PartitionRedeemed(_derivatives[i], msg.sender, withdrawals_[i]);

        }

        return withdrawals_;

    }

}
////// src/ProportionalLiquidity.sol
/* pragma solidity ^0.5.0; */

/* import "./Assimilators.sol"; */

/* import "./ShellStorage.sol"; */

/* import "./UnsafeMath64x64.sol"; */

/* import "./ShellMath.sol"; */


library ProportionalLiquidity {

    using ABDKMath64x64 for uint;
    using ABDKMath64x64 for int128;
    using UnsafeMath64x64 for int128;

    event Transfer(address indexed from, address indexed to, uint256 value);

    int128 constant ONE = 0x10000000000000000;
    int128 constant ONE_WEI = 0x12;

    function proportionalDeposit (
        ShellStorage.Shell storage shell,
        uint256 _deposit
    ) external returns (
        uint256 shells_,
        uint[] memory
    ) {

        int128 __deposit = _deposit.divu(1e18);

        uint _length = shell.assets.length;

        uint[] memory deposits_ = new uint[](_length);
        
        ( int128 _oGLiq, int128[] memory _oBals ) = getGrossLiquidityAndBalances(shell);

        if (_oGLiq == 0) {

            for (uint i = 0; i < _length; i++) {

                deposits_[i] = Assimilators.intakeNumeraire(shell.assets[i].addr, __deposit.mul(shell.weights[i]));

            }

        } else {

            int128 _multiplier = __deposit.div(_oGLiq);

            for (uint i = 0; i < _length; i++) {

                deposits_[i] = Assimilators.intakeNumeraire(shell.assets[i].addr, _oBals[i].mul(_multiplier));

            }

        }
        
        int128 _totalShells = shell.totalSupply.divu(1e18);
        
        int128 _newShells = _totalShells > 0
            ? __deposit.div(_oGLiq).mul(_totalShells)
            : __deposit;

        requireLiquidityInvariant(
            shell, 
            _totalShells,
            _newShells, 
            _oGLiq, 
            _oBals
        );        

        mint(shell, msg.sender, shells_ = _newShells.mulu(1e18));

        return (shells_, deposits_);

    }
    
    
    function viewProportionalDeposit (
        ShellStorage.Shell storage shell,
        uint256 _deposit
    ) external view returns (
        uint shells_,
        uint[] memory
    ) {

        int128 __deposit = _deposit.divu(1e18);

        uint _length = shell.assets.length;

        ( int128 _oGLiq, int128[] memory _oBals ) = getGrossLiquidityAndBalances(shell);

        uint[] memory deposits_ = new uint[](_length);

        if (_oGLiq == 0) {

            for (uint i = 0; i < _length; i++) {

                deposits_[i] = Assimilators.viewRawAmount(
                    shell.assets[i].addr,
                    __deposit.mul(shell.weights[i])
                );

            }

        } else {

            int128 _multiplier = __deposit.div(_oGLiq);

            for (uint i = 0; i < _length; i++) {

                deposits_[i] = Assimilators.viewRawAmount(
                    shell.assets[i].addr,
                    _oBals[i].mul(_multiplier)
                );

            }

        }
        
        int128 _totalShells = shell.totalSupply.divu(1e18);
        
        int128 _newShells = _totalShells > 0
            ? __deposit.div(_oGLiq).mul(_totalShells)
            : __deposit;
        
        shells_ = _newShells.mulu(1e18);

        return ( shells_, deposits_ );

    }

    function proportionalWithdraw (
        ShellStorage.Shell storage shell,
        uint256 _withdrawal
    ) external returns (
        uint[] memory
    ) {

        uint _length = shell.assets.length;

        ( int128 _oGLiq, int128[] memory _oBals ) = getGrossLiquidityAndBalances(shell);

        uint[] memory withdrawals_ = new uint[](_length);
        
        int128 _totalShells = shell.totalSupply.divu(1e18);
        int128 __withdrawal = _withdrawal.divu(1e18);

        int128 _multiplier = __withdrawal
            .mul(ONE - shell.epsilon)
            .div(_totalShells);

        for (uint i = 0; i < _length; i++) {

            withdrawals_[i] = Assimilators.outputNumeraire(
                shell.assets[i].addr,
                msg.sender,
                _oBals[i].mul(_multiplier)
            );

        }

        requireLiquidityInvariant(
            shell, 
            _totalShells, 
            __withdrawal.neg(), 
            _oGLiq, 
            _oBals
        );
        
        burn(shell, msg.sender, _withdrawal);

        return withdrawals_;

    }
    
    function viewProportionalWithdraw (
        ShellStorage.Shell storage shell,
        uint256 _withdrawal
    ) external view returns (
        uint[] memory
    ) {

        uint _length = shell.assets.length;

        ( int128 _oGLiq, int128[] memory _oBals ) = getGrossLiquidityAndBalances(shell);

        uint[] memory withdrawals_ = new uint[](_length);

        int128 _multiplier = _withdrawal.divu(1e18)
            .mul(ONE - shell.epsilon)
            .div(shell.totalSupply.divu(1e18));

        for (uint i = 0; i < _length; i++) {

            withdrawals_[i] = Assimilators.viewRawAmount(shell.assets[i].addr, _oBals[i].mul(_multiplier));

        }

        return withdrawals_;

    }

    function getGrossLiquidityAndBalances (
        ShellStorage.Shell storage shell
    ) internal view returns (
        int128 grossLiquidity_,
        int128[] memory
    ) {
        
        uint _length = shell.assets.length;

        int128[] memory balances_ = new int128[](_length);
        
        for (uint i = 0; i < _length; i++) {

            int128 _bal = Assimilators.viewNumeraireBalance(shell.assets[i].addr);
            
            balances_[i] = _bal;
            grossLiquidity_ += _bal;
            
        }
        
        return (grossLiquidity_, balances_);

    }
    
    function requireLiquidityInvariant (
        ShellStorage.Shell storage shell,
        int128 _shells,
        int128 _newShells,
        int128 _oGLiq,
        int128[] memory _oBals
    ) private {
    
        ( int128 _nGLiq, int128[] memory _nBals ) = getGrossLiquidityAndBalances(shell);
        
        int128 _beta = shell.beta;
        int128 _delta = shell.delta;
        int128[] memory _weights = shell.weights;
        
        int128 _omega = ShellMath.calculateFee(_oGLiq, _oBals, _beta, _delta, _weights);

        int128 _psi = ShellMath.calculateFee(_nGLiq, _nBals, _beta, _delta, _weights);

        ShellMath.enforceLiquidityInvariant(_shells, _newShells, _oGLiq, _nGLiq, _omega, _psi);
        
    }

    function burn (ShellStorage.Shell storage shell, address account, uint256 amount) private {

        shell.balances[account] = burn_sub(shell.balances[account], amount);

        shell.totalSupply = burn_sub(shell.totalSupply, amount);

        emit Transfer(msg.sender, address(0), amount);

    }

    function mint (ShellStorage.Shell storage shell, address account, uint256 amount) private {

        shell.totalSupply = mint_add(shell.totalSupply, amount);

        shell.balances[account] = mint_add(shell.balances[account], amount);

        emit Transfer(address(0), msg.sender, amount);

    }

    function mint_add(uint x, uint y) private pure returns (uint z) {

        require((z = x + y) >= x, "Shell/mint-overflow");

    }

    function burn_sub(uint x, uint y) private pure returns (uint z) {

        require((z = x - y) <= x, "Shell/burn-underflow");

    }


}
////// src/SelectiveLiquidity.sol
/* pragma solidity ^0.5.0; */

/* import "./Assimilators.sol"; */

/* import "./ShellStorage.sol"; */

/* import "./ShellMath.sol"; */

/* import "./UnsafeMath64x64.sol"; */

/* import "abdk-libraries-solidity/ABDKMath64x64.sol"; */


library SelectiveLiquidity {

    using ABDKMath64x64 for int128;
    using UnsafeMath64x64 for int128;

    event Transfer(address indexed from, address indexed to, uint256 value);

    int128 constant ONE = 0x10000000000000000;

    function selectiveDeposit (
        ShellStorage.Shell storage shell,
        address[] calldata _derivatives,
        uint[] calldata _amounts,
        uint _minShells
    ) external returns (
        uint shells_
    ) {

        (   int128 _oGLiq,
            int128 _nGLiq,
            int128[] memory _oBals,
            int128[] memory _nBals ) = getLiquidityDepositData(shell, _derivatives, _amounts);

        int128 _shells = ShellMath.calculateLiquidityMembrane(shell, _oGLiq, _nGLiq, _oBals, _nBals);

        shells_ = _shells.mulu(1e18);

        require(_minShells < shells_, "Shell/under-minimum-shells");

        mint(shell, msg.sender, shells_);

    }

    function viewSelectiveDeposit (
        ShellStorage.Shell storage shell,
        address[] calldata _derivatives,
        uint[] calldata _amounts
    ) external view returns (
        uint shells_
    ) {

        (   int128 _oGLiq,
            int128 _nGLiq,
            int128[] memory _oBals,
            int128[] memory _nBals ) = viewLiquidityDepositData(shell, _derivatives, _amounts);

        int128 _shells = ShellMath.calculateLiquidityMembrane(shell, _oGLiq, _nGLiq, _oBals, _nBals);

        shells_ = _shells.mulu(1e18);

    }

    function selectiveWithdraw (
        ShellStorage.Shell storage shell,
        address[] calldata _derivatives,
        uint[] calldata _amounts,
        uint _maxShells
    ) external returns (
        uint256 shells_
    ) {

        (   int128 _oGLiq,
            int128 _nGLiq,
            int128[] memory _oBals,
            int128[] memory _nBals ) = getLiquidityWithdrawData(shell, _derivatives, msg.sender, _amounts);

        int128 _shells = ShellMath.calculateLiquidityMembrane(shell, _oGLiq, _nGLiq, _oBals, _nBals);

        _shells = _shells.neg().us_mul(ONE + shell.epsilon);

        shells_ = _shells.mulu(1e18);

        require(shells_ < _maxShells, "Shell/above-maximum-shells");

        burn(shell, msg.sender, shells_);

    }

    function viewSelectiveWithdraw (
        ShellStorage.Shell storage shell,
        address[] calldata _derivatives,
        uint[] calldata _amounts
    ) external view returns (
        uint shells_
    ) {

        (   int128 _oGLiq,
            int128 _nGLiq,
            int128[] memory _oBals,
            int128[] memory _nBals ) = viewLiquidityWithdrawData(shell, _derivatives, _amounts);

        int128 _shells = ShellMath.calculateLiquidityMembrane(shell, _oGLiq, _nGLiq, _oBals, _nBals);

        _shells = _shells.neg().us_mul(ONE + shell.epsilon);

        shells_ = _shells.mulu(1e18);

    }

    function getLiquidityDepositData (
        ShellStorage.Shell storage shell,
        address[] memory _derivatives,
        uint[] memory _amounts
    ) private returns (
        int128 oGLiq_,
        int128 nGLiq_,
        int128[] memory,
        int128[] memory
    ) {

        uint _length = shell.weights.length;
        int128[] memory oBals_ = new int128[](_length);
        int128[] memory nBals_ = new int128[](_length);

        for (uint i = 0; i < _derivatives.length; i++) {

            ShellStorage.Assimilator memory _assim = shell.assimilators[_derivatives[i]];

            require(_assim.addr != address(0), "Shell/unsupported-derivative");

            if ( nBals_[_assim.ix] == 0 && 0 == oBals_[_assim.ix]) {

                ( int128 _amount, int128 _balance ) = Assimilators.intakeRawAndGetBalance(_assim.addr, _amounts[i]);

                nBals_[_assim.ix] = _balance;

                oBals_[_assim.ix] = _balance.sub(_amount);

            } else {

                int128 _amount = Assimilators.intakeRaw(_assim.addr, _amounts[i]);

                nBals_[_assim.ix] = nBals_[_assim.ix].add(_amount);

            }

        }

        return completeLiquidityData(shell, oBals_, nBals_);

    }

    function getLiquidityWithdrawData (
        ShellStorage.Shell storage shell,
        address[] memory _derivatives,
        address _rcpnt,
        uint[] memory _amounts
    ) private returns (
        int128 oGLiq_,
        int128 nGLiq_,
        int128[] memory,
        int128[] memory
    ) {

        uint _length = shell.weights.length;
        int128[] memory oBals_ = new int128[](_length);
        int128[] memory nBals_ = new int128[](_length);

        for (uint i = 0; i < _derivatives.length; i++) {

            ShellStorage.Assimilator memory _assim = shell.assimilators[_derivatives[i]];

            require(_assim.addr != address(0), "Shell/unsupported-derivative");

            if ( nBals_[_assim.ix] == 0 && 0 == oBals_[_assim.ix]) {

                ( int128 _amount, int128 _balance ) = Assimilators.outputRawAndGetBalance(_assim.addr, _rcpnt, _amounts[i]);

                nBals_[_assim.ix] = _balance;
                oBals_[_assim.ix] = _balance.sub(_amount);

            } else {

                int128 _amount = Assimilators.outputRaw(_assim.addr, _rcpnt, _amounts[i]);

                nBals_[_assim.ix] = nBals_[_assim.ix].add(_amount);

            }

        }

        return completeLiquidityData(shell, oBals_, nBals_);

    }

    function viewLiquidityDepositData (
        ShellStorage.Shell storage shell,
        address[] memory _derivatives,
        uint[] memory _amounts
    ) private view returns (
        int128 oGLiq_,
        int128 nGLiq_,
        int128[] memory,
        int128[] memory
    ) {

        uint _length = shell.assets.length;
        int128[] memory oBals_ = new int128[](_length);
        int128[] memory nBals_ = new int128[](_length);

        for (uint i = 0; i < _derivatives.length; i++) {

            ShellStorage.Assimilator memory _assim = shell.assimilators[_derivatives[i]];

            require(_assim.addr != address(0), "Shell/unsupported-derivative");

            if ( nBals_[_assim.ix] == 0 && 0 == oBals_[_assim.ix]) {

                ( int128 _amount, int128 _balance ) = Assimilators.viewNumeraireAmountAndBalance(_assim.addr, _amounts[i]);

                nBals_[_assim.ix] = _balance.add(_amount);

                oBals_[_assim.ix] = _balance;

            } else {

                int128 _amount = Assimilators.viewNumeraireAmount(_assim.addr, _amounts[i]);

                nBals_[_assim.ix] = nBals_[_assim.ix].add(_amount);

            }

        }

        return completeLiquidityData(shell, oBals_, nBals_);

    }

    function viewLiquidityWithdrawData (
        ShellStorage.Shell storage shell,
        address[] memory _derivatives,
        uint[] memory _amounts
    ) private view ret...

// [truncated — 114023 bytes total]

Read Contract

allowance 0xdd62ed3e → uint256
assimilator 0x3cae77f7 → address
balanceOf 0x70a08231 → uint256
chi 0xc92aecc4 → address
decimals 0x313ce567 → uint8
derivatives 0xc0046e39 → address
frozen 0x054f7d9c → bool
liquidity 0x1a686502 → uint256, uint256[]
name 0x06fdde03 → string
numeraires 0xa8e9d528 → address
owner 0x8da5cb5b → address
partitionTickets 0xba443d33 → bool
partitioned 0x0ceb9386 → bool
reserves 0x8334278d → address
shell 0xf11d2ff4 → int128, int128, int128, int128, int128, uint256
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
viewOriginSwap 0x838e6a22 → uint256
viewPartitionClaims 0x7ec8c857 → uint256[]
viewProportionalDeposit 0x3cea3c89 → uint256, uint256[]
viewProportionalWithdraw 0xbbde3adc → uint256[]
viewSelectiveDeposit 0x5ccd4afd → uint256
viewSelectiveWithdraw 0x91953189 → uint256
viewShell 0xf8bda7b9 → uint256, uint256, uint256, uint256, uint256
viewTargetSwap 0x525d0da7 → uint256

Write Contract 16 functions

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

approve 0x095ea7b3
address _spender
uint256 _amount
returns: bool
excludeDerivative 0xc912ff7a
address _derivative
originSwap 0x0b2583c8
address _origin
address _target
uint256 _originAmount
uint256 _minTargetAmount
uint256 _deadline
returns: uint256
originSwapDiscountCHI 0x9d16b2c5
address _origin
address _target
uint256 _originAmount
uint256 _minTargetAmount
uint256 _deadline
returns: uint256
partition 0x2a14b80a
No parameters
partitionedWithdraw 0x96677086
address[] _tokens
uint256[] _amounts
returns: uint256[]
proportionalDeposit 0x4737287d
uint256 _deposit
uint256 _deadline
returns: uint256, uint256[]
proportionalWithdraw 0x775d9865
uint256 _shellsToBurn
uint256 _deadline
returns: uint256[]
selectiveDeposit 0x51dbb2a7
address[] _derivatives
uint256[] _amounts
uint256 _minShells
uint256 _deadline
returns: uint256
selectiveWithdraw 0x546e0c9b
address[] _derivatives
uint256[] _amounts
uint256 _maxShells
uint256 _deadline
returns: uint256
setFrozen 0x7e932d32
bool _toFreezeOrNotToFreeze
setParams 0xd828bb88
uint256 _alpha
uint256 _beta
uint256 _feeAtHalt
uint256 _epsilon
uint256 _lambda
targetSwap 0x72b4129a
address _origin
address _target
uint256 _maxOriginAmount
uint256 _targetAmount
uint256 _deadline
returns: uint256
transfer 0xa9059cbb
address _recipient
uint256 _amount
returns: bool
transferFrom 0x23b872dd
address _sender
address _recipient
uint256 _amount
returns: bool
transferOwnership 0xf2fde38b
address _newOwner

Recent Transactions

No transactions found for this address