diff --git a/crates/test_fixtures/abis/RaindexV6.json b/crates/test_fixtures/abis/RaindexV6.json index 54621ad6fe..dc1e3cc85d 100644 --- a/crates/test_fixtures/abis/RaindexV6.json +++ b/crates/test_fixtures/abis/RaindexV6.json @@ -2352,7 +2352,7 @@ } ], "bytecode": { - "object": "0x6080604052348015600e575f80fd5b5060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055615eed806100405f395ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c8063613255ab11610093578063ac9650d811610063578063ac9650d81461022b578063d7e442ec1461024b578063d9d98ce41461025e578063fa50118214610271575f80fd5b8063613255ab146101ad57806369c72856146101c0578063709fb8a5146101e85780639235084d146101fb575f80fd5b80632fbc4ba0116100ce5780632fbc4ba01461015157806341d1514f146101665780635cffe9de14610187578063607461191461019a575f80fd5b806301ffc9a7146100f45780631f69cb751461011c5780632cb77e9f1461012f575b5f80fd5b6101076101023660046148e8565b610284565b60405190151581526020015b60405180910390f35b61010761012a366004614950565b6102ba565b61010761013d3660046149bb565b5f9081526020819052604090205460011490565b61016461015f3660046149f1565b6103c2565b005b610179610174366004614a56565b610521565b604051908152602001610113565b610107610195366004614a94565b610535565b6101646101a83660046149f1565b610635565b6101796101bb366004614b2b565b6107c8565b6101d36101ce366004614b5c565b610830565b60408051928352602083019190915201610113565b6101076101f6366004614b8e565b610fc9565b61020e610209366004614bd8565b61130c565b604080519315158452602084019290925290820152606001610113565b61023e610239366004614c0f565b6113ce565b6040516101139190614c7c565b610164610259366004614c0f565b6114b4565b61017961026c366004614cde565b61150e565b61016461027f366004615150565b6115a8565b5f6001600160e01b0319821663e414309160e01b14806102b457506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6102c3611a9a565b6102d06020850185614b2b565b6001600160a01b0316336001600160a01b03161461031f576102f56020850185614b2b565b6040516335252be360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b5f61033161032c8661520a565b611ab5565b5f818152602081905260409020549091505f19016103a4575f818152602081905260408082209190915551600192507f09d18501db0080ca2d6cd7c17fa7255daff4b2d503ea93b76ff68b6752ea8e639061039190339084908990615360565b60405180910390a16103a4818585611ae4565b506103bb60015f80516020615ecd83398151915255565b9392505050565b6103ca611a9a565b3385856103d8838383611b1b565b6103e2865f611b4c565b610417576040516306dde9c360e41b81523360048201526001600160a01b038916602482015260448101889052606401610316565b5f80610424338b8a611b86565b604080513381526001600160a01b038e1660208201529081018c90526060810183905291935091507f7f9dfa19cf1cc2f806f2f860fbc9c056b601fb1afc0e9b843dfe5c63616268e69060800160405180910390a15f80610487338d8d8d611c06565b909250905087156104fd5760408051600581526001600160a01b038e1660208201528082018d9052606081018490526080810183905260ff851660a082015260c081019091526104fd906104ee905b60408051600181526020810192909252818101905290565b6104f88a8c615424565b611cf6565b5050505050505061051a60015f80516020615ecd83398151915255565b5050505050565b5f61052d848484611ec4565b949350505050565b5f61054a6001600160a01b038616878661204e565b6040516323e30c8b60e01b81525f906001600160a01b038816906323e30c8b906105829033908a908a9087908b908b906004016154e4565b6020604051808303815f875af115801561059e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c29190615528565b90507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9811461060757604051630b6c58a960e31b815260048101829052602401610316565b61062887306106165f89615553565b6001600160a01b038a16929190612083565b5060019695505050505050565b61063d611a9a565b33858561064b838383611b1b565b5f8080806106598a82611b4c565b61068d57604051623a3a4d60e21b81523360048201526001600160a01b038d166024820152604481018c9052606401610316565b5f610699338e8e611ec4565b90506106a58b826120bf565b94506106b3338e8e886120db565b90935091505f6106c4338f88612152565b80965081925050507f8045c25080b0868951141ed0a91720bcad09a8364a2b3109ee1fd49c1f0bc8b8338f8f8f8a86604051610736969594939291906001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b60405180910390a1505060408051600681526001600160a01b038e1660208201528082018d9052606081018490526080810183905260a081018c905260ff851660c0820152600160e08201908152610100820182905261012082019092529089156107a9576107a9816104f88c8e615424565b50505050505050505061051a60015f80516020615ecd83398151915255565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa15801561080c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b49190615528565b5f8061083a611a9a565b6108476080840184615566565b90505f0361086857604051639c95219f60e01b815260040160405180910390fd5b610870614810565b61087861483c565b5f60405180606001604052808780608001906108949190615566565b5f8181106108a4576108a46155ac565b90506020028101906108b691906155c0565b6108c090806155de565b6108ce9060408101906155f2565b6108db60808b018b615566565b5f8181106108eb576108eb6155ac565b90506020028101906108fd91906155c0565b60200135818110610910576109106155ac565b6109269260206040909202019081019150614b2b565b6001600160a01b031681526020016109416080890189615566565b5f818110610951576109516155ac565b905060200281019061096391906155c0565b61096d90806155de565b61097b9060608101906155f2565b61098860808b018b615566565b5f818110610998576109986155ac565b90506020028101906109aa91906155c0565b604001358181106109bd576109bd6155ac565b6109d39260206040909202019081019150614b2b565b6001600160a01b03168152602088810135910152905060605f6109f96080890189615566565b604080516001909201602002820181528501519093505f9250610a1d915082611b4c565b610a3a5760405163315f9e2360e21b815260040160405180910390fd5b5f5b610a4960808a018a615566565b905081108015610a6357506040840151610a63905f611b4c565b15610e7157610a7560808a018a615566565b82818110610a8557610a856155ac565b9050602002810190610a9791906155c0565b610aa090615638565b9550855f01519450835f01516001600160a01b03168560400151876020015181518110610acf57610acf6155ac565b60200260200101515f01516001600160a01b0316141580610b2a575083602001516001600160a01b03168560600151876040015181518110610b1357610b136155ac565b60200260200101515f01516001600160a01b031614155b15610b485760405163936bb5ad60e01b815260040160405180910390fd5b610b5b85876020015188604001516121bb565b5f610b6586611ab5565b5f81815260208190526040902054909150610bca578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a1610e68565b5f610c278789602001518a60400151338c606001515f67ffffffffffffffff811115610bf857610bf8614d08565b604051908082528060200260200182016040528015610c21578160200160208202803683370190505b5061222d565b90505f610c458c604001358360600151611b4c90919063ffffffff16565b15610c9b578751604080513381526001600160a01b03909216602083015281018490527fe3151dc8cb7a54ffc4baabd28c1f241c94d510b5e5b502491ac3cad6c16316d5906060015b60405180910390a1610e5a565b6040820151610caa905f611b4c565b1580610cc257506060820151610cc0905f611b4c565b155b15610d0f578751604080513381526001600160a01b03909216602083015281018490527f500b713857325f9e6dcb52ae832eca9109d107ed1aae9cb4928b4c1e13f051aa90606001610c8e565b600190505f808d6060016020810190610d2891906156ce565b15610d6e576040808a015190850151610d40916120bf565b6060850151909250610d5290836126f2565b60408a0151909150610d64908361273f565b60408a0152610dd5565b5f610d8a856040015186606001516126f290919063ffffffff16565b9050610da38a60400151826120bf90919063ffffffff16565b9150610dbc85606001518361276f90919063ffffffff16565b60408b0151909350610dce908361273f565b60408b0152505b610ddf8c8261279f565b9b50610deb8d8361279f565b9c50610df782856127cf565b610e018185612890565b7f194f1feb3b4d7076a2c272e774e792e0c48bb8c7aa1a9a3671c1cd6da9e6b4c1338c8484604051610e3694939291906157f6565b60405180910390a187516001018089526020028801849052610e5784612a3c565b50505b8480610e635750805b945050505b50600101610a3c565b505f610e8360808a0160608b016156ce565b610e8d5786610e8f565b875b9050610e9c818a35612c7f565b15610ec45760405163573b6f4160e01b81528935600482015260248101829052604401610316565b50610ed433846020015189612152565b505f9050610ee560a08a018a6158e0565b9050118015610ef15750805b15610f635760208301518351339163691f9ed7918a8a610f1460a08f018f6158e0565b6040518763ffffffff1660e01b8152600401610f35969594939291906154e4565b5f604051808303815f87803b158015610f4c575f80fd5b505af1158015610f5e573d5f803e3d5ffd5b505050505b610f7133845f015188611b86565b50505f5b8251811015610fa857610fa0838281518110610f9357610f936155ac565b6020026020010151612cb9565b600101610f75565b505050505050610fc460015f80516020615ecd83398151915255565b915091565b5f610fd2611a9a565b5f61102f61102a610fe38780615923565b610ff19060408101906158e0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612dc392505050565b612e34565b90505f811161105157604051632cff108b60e21b815260040160405180910390fd5b6001811161107257604051633c8270bd60e21b815260040160405180910390fd5b61107f60208601866155f2565b90505f036110a057604051636c44ef8f60e01b815260040160405180910390fd5b6110ad60408601866155f2565b90505f036110ce5760405163540e5f0b60e01b815260040160405180910390fd5b6040805160a081019091523381525f90602081016110ec8880615923565b6110f590615937565b815260200187806020019061110a91906155f2565b808060200260200160405190810160405280939291908181526020015f905b828210156111555761114660408302860136819003810190615942565b81526020019060010190611129565b505050918352505060200161116d60408901896155f2565b808060200260200160405190810160405280939291908181526020015f905b828210156111b8576111a960408302860136819003810190615942565b8152602001906001019061118c565b50505050508152602001876060013581525090505f6111d682611ab5565b5f818152602081905260409020549091501580156112f1575f828152602081905260409081902060019055835190517f87491344dfbcf91f6cbbc610cbbeedc85313d37a02df0c93527f7ea5f8db717f91611234918590879061595c565b60405180910390a15f61124a60a08a018a6158e0565b905011156112e65761129b61126260a08a018a6158e0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612e4e92505050565b82517fd46c2c56b35c8210e9e712ec3f02242d5fc90187c0ac8ed80cc33626846ec36990836112cd60a08c018c6158e0565b6040516112dd9493929190615983565b60405180910390a15b6112f1828888611ae4565b93505050506103bb60015f80516020615ecd83398151915255565b5f80808061132661131d86806155de565b61032c9061520a565b5f8181526020819052604090205490915060011461134d57505f92508291508190506113c7565b61137261135a86806155de565b6113639061520a565b866020013587604001356121bb565b5f6113b061138087806155de565b6113899061520a565b60208801356040890135336113a160608c018c615566565b6113aa916159b5565b5f610bf8565b905060018160400151826060015194509450945050505b9193909250565b604080515f8152602081019091526060908267ffffffffffffffff8111156113f8576113f8614d08565b60405190808252806020026020018201604052801561142b57816020015b60608152602001906001900390816114165790505b5091505f5b838110156114ac576114873086868481811061144e5761144e6155ac565b905060200281019061146091906158e0565b85604051602001611473939291906159d4565b604051602081830303815290604052612e79565b838281518110611499576114996155ac565b6020908102919091010152600101611430565b505092915050565b6114bc611a9a565b604080515f808252602082019092526114f4916114e9565b60608152602001906001900390816114d45790505b506104f88385615424565b61150a60015f80516020615ecd83398151915255565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa158015611552573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115769190615528565b5f036115a057604051633c5bf76960e21b81526001600160a01b0384166004820152602401610316565b505f92915050565b6115b0611a9a565b835185516001600160a01b039182169116036115df57604051630a98f1f360e21b815260040160405180910390fd5b83604001518360400135815181106115f9576115f96155ac565b60200260200101515f01516001600160a01b03168560600151846020013581518110611627576116276155ac565b60200260200101515f01516001600160a01b03161415806116a0575060408501518051843590811061165b5761165b6155ac565b60200260200101515f01516001600160a01b03168460600151846060013581518110611689576116896155ac565b60200260200101515f01516001600160a01b031614155b156116be5760405163936bb5ad60e01b815260040160405180910390fd5b84606001518360200135815181106116d8576116d86155ac565b60200260200101515f01516001600160a01b03168560400151845f013581518110611705576117056155ac565b60200260200101515f01516001600160a01b03160361173757604051631cd2f1c760e21b815260040160405180910390fd5b5f61174186611ab5565b5f818152602081905260409020549091506117a7578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a150611a84565b5f6117b186611ab5565b5f81815260208190526040902054909150611818578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a15050611a84565b7f6fa7f4c28634b0a9d6831401c45ae468195fb63aed07308935c35374ff5d9e393388888860405161184d94939291906159f7565b60405180910390a1505083515f906118719087908635906020880135908686610bf8565b90505f6118a086866040013587606001358a5f0151885f67ffffffffffffffff811115610bf857610bf8614d08565b90505f6118ad8383612f19565b90506118bc815f0151846127cf565b6118ca8160200151836127cf565b6118d8816040015184612890565b6118e6816060015183612890565b6118ef83612cb9565b6118f882612cb9565b606081015181515f9161190b919061273f565b90505f6119298360400151846020015161273f90919063ffffffff16565b9050611935825f612c7f565b806119455750611945815f612c7f565b1561196357604051630d86822160e01b815260040160405180910390fd5b611997338b606001518a6020013581518110611981576119816155ac565b60200260200101515f01518a6080013585611c06565b50506119cd338a606001518a60600135815181106119b7576119b76155ac565b60200260200101515f01518a60a0013584611c06565b5050604080513381528451602080830191909152850151818301529084015160608083019190915284015160808201527fd9fa84dd790c969daa5c33d8050dc06b4a9b59d5b42e2be5f5e8ae20447f618d925060a001905060405180910390a1611a3683612a3c565b611a3f82612a3c565b80516001600160e01b0316158015611a62575060208101516001600160e01b0316155b15611a80576040516321badf1f60e01b815260040160405180910390fd5b5050505b61051a60015f80516020615ecd83398151915255565b611aa2612f67565b60025f80516020615ecd83398151915255565b5f81604051602001611ac79190615a73565b604051602081830303815290604052805190602001209050919050565b604080516002815260208101859052338183015260608101909152611b1690611b0c906104d6565b6104f88385615424565b505050565b80611b16576040516305dbdfd960e41b81526001600160a01b03808516600483015283166024820152604401610316565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d611b7a84848484612f98565b12979650505050505050565b5f805f611b928561306c565b9050611b9e845f612c7f565b15611bbc57604051632eaefac360e21b815260040160405180910390fd5b5f80611bc886846130d2565b9150915080611bdd57611bda82615a85565b91505b8115611bf857611bf86001600160a01b038816893085612083565b50925090505b935093915050565b5f80611c128382612c7f565b15611c335760405163793a8f5560e01b815260048101849052602401610316565b83611c5157611c43868685612152565b505f9250829150611ced9050565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611c8b828661279f565b9050611c97815f612c7f565b15611cb85760405163c5e12af560e01b815260048101829052602401610316565b6001600160a01b038089165f908152600160209081526040808320938b16835292815282822089835290522081905590925090505b94509492505050565b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b8651811015611eba57868181518110611d5d57611d5d6155ac565b602002602001015193505f845f015160400151511115611eb2575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001611dd58d8a602001516130ff565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401611e009190615af5565b5f60405180830381865afa158015611e1a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611e419190810190615bed565b9150505f81511115611eb05784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490611e82908a908590600401615ca3565b5f604051808303815f87803b158015611e99575f80fd5b505af1158015611eab573d5f803e3d5ffd5b505050505b505b600101611d42565b5050505050505050565b5f8115611efe57506001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546103bb565b5f611f08846133e1565b6040516370a0823160e01b81526001600160a01b0387811660048301529192505f91611f8091908716906370a0823190602401602060405180830381865afa158015611f56573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f7a9190615528565b836133ed565b50604051636eb1769f60e11b81526001600160a01b0388811660048301523060248301529192505f91611fff919088169063dd62ed3e90604401602060405180830381865afa158015611fd5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ff99190615528565b846133ed565b506001600160a01b038089165f908152600160209081526040808320938b168352928152828220828052905220549091506120449061203e84846120bf565b9061279f565b93505050506103bb565b61205b838383600161342d565b611b1657604051635274afe760e01b81526001600160a01b0384166004820152602401610316565b61209184848484600161348f565b6120b957604051635274afe760e01b81526001600160a01b0385166004820152602401610316565b50505050565b5f6120ca8383612c7f565b6120d457816103bb565b5090919050565b5f806120e78382612c7f565b156121085760405163793a8f5560e01b815260048101849052602401610316565b8361211857611c43868685611b86565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611c8b828661273f565b5f805f61215e8561306c565b905061216a845f612c7f565b1561218857604051632d1671a360e11b815260040160405180910390fd5b5f61219385836130d2565b50905080156121b0576121b06001600160a01b038716888361204e565b969095509350505050565b826060015181815181106121d1576121d16155ac565b60200260200101515f01516001600160a01b0316836040015183815181106121fb576121fb6155ac565b60200260200101515f01516001600160a01b031603611b1657604051631cd2f1c760e21b815260040160405180910390fd5b6122356148a3565b60408051600480825260a082019092526060915f9190816020015b60608152602001906001900390816122505790505090506122a56122738a611ab5565b8a51604080516003815260208101939093526001600160a01b0391821683820152908916606083015260808201905290565b8160018003815181106122ba576122ba6155ac565b60200260200101819052505f6122ef8a604001518a815181106122df576122df6155ac565b60200260200101515f01516133e1565b90505f6123418b5f01518c604001518c8151811061230f5761230f6155ac565b60200260200101515f01518d604001518d81518110612330576123306155ac565b602002602001015160200151611ec4565b90506123d08b604001518b8151811061235c5761235c6155ac565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d604001518d8151811061238e5761238e6155ac565b602002602001015160200151845f801b60408051600581526020810196909652858101949094526060850192909252608084015260a083015260c08201905290565b836001600303815181106123e6576123e66155ac565b602002602001018190525050505f61240d8a6060015189815181106122df576122df6155ac565b90505f61244e8b5f01518c606001518b8151811061242d5761242d6155ac565b60200260200101515f01518d606001518c81518110612330576123306155ac565b905061249b8b606001518a81518110612469576124696155ac565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d606001518c8151811061238e5761238e6155ac565b836001600403815181106124b1576124b16155ac565b602002602001018190525050506124c881866130ff565b9150505f885f01516001600160a01b031690505f808a602001515f01516001600160a01b031663d04dfe236040518060e001604052808e60200151602001516001600160a01b0316815260200161252887305f9182526020526040902090565b81526020018e602001516040015181526020015f81526020018781526020015f67ffffffffffffffff81111561256057612560614d08565b604051908082528060200260200182016040528015612589578160200160208202803683370190505b508152602001898152506040518263ffffffff1660e01b81526004016125af9190615af5565b5f60405180830381865afa1580156125c9573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125f09190810190615bed565b9150915060028251101561261c578151604051630fbb8e5560e21b815260040161031691815260200190565b602082015160408301518551612670908790600490811061263f5761263f6155ac565b6020026020010151600381518110612659576126596155ac565b6020026020010151826120bf90919063ffffffff16565b60408051600281526020810183905280820185905260608101909152909150866002815181106126a2576126a26155ac565b60200260200101819052506040518060e001604052808e81526020018c81526020018281526020018381526020018781526020018681526020018481525096505050505050509695505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d8480612722868686866134fc565b915091505f612731838361361b565b9a9950505050505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613668565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613692565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613bcf565b8181608001516004815181106127e7576127e76155ac565b6020026020010151600481518110612801576128016155ac565b6020026020010181815250506120b9815f01515f0151826080015160048151811061282e5761282e6155ac565b60200260200101515f81518110612847576128476155ac565b60200260200101515f1c8360800151600481518110612868576128686155ac565b6020026020010151600281518110612882576128826155ac565b6020026020010151856120db565b8181608001516003815181106128a8576128a86155ac565b60200260200101516004815181106128c2576128c26155ac565b6020908102919091010152805151608082015180515f919060039081106128eb576128eb6155ac565b60200260200101515f81518110612904576129046155ac565b60200260200101515f1c90505f8360800151600381518110612928576129286155ac565b6020026020010151600281518110612942576129426155ac565b602002602001015190505f801b81036129e95761295f855f612c7f565b156129805760405163793a8f5560e01b815260048101869052602401610316565b6001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546129b7908661279f565b6001600160a01b038085165f9081526001602090815260408083209387168352928152828220858352905220556129f8565b6129f583838388611c06565b50505b7f4cb6e22a3e7e651d7cf0376cff48f20f5007a54147777865be7f5f6c38c50f4a338560800151604051612a2d929190615cbb565b60405180910390a15050505050565b60c08101515115612ab6578051602090810151015160a082015160c083015160405163012c676d60e21b81526001600160a01b03909316926304b19db492612a88929091600401615ca3565b5f604051808303815f87803b158015612a9f575f80fd5b505af1158015612ab1573d5f803e3d5ffd5b505050505b5f815f0151602001515f01516001600160a01b031663d04dfe236040518060e00160405280855f015160200151602001516001600160a01b03168152602001612b0c8660a00151305f9182526020526040902090565b8152602001855f01516020015160400151815260200160018152602001856080015181526020015f67ffffffffffffffff811115612b4c57612b4c614d08565b604051908082528060200260200182016040528015612b75578160200160208202803683370190505b5081526020015f604051908082528060200260200182016040528015612ba5578160200160208202803683370190505b508152506040518263ffffffff1660e01b8152600401612bc59190615af5565b5f60405180830381865afa158015612bdf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612c069190810190615bed565b9150505f8151111561150a578151602090810151015160a083015160405163012c676d60e21b81526001600160a01b03909216916304b19db491612c4e918590600401615ca3565b5f604051808303815f87803b158015612c65575f80fd5b505af1158015612c77573d5f803e3d5ffd5b505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d612cad84848484612f98565b13979650505050505050565b5f8160800151600381518110612cd157612cd16155ac565b6020026020010151600281518110612ceb57612ceb6155ac565b602002602001015190505f801b810361150a57815151608083015180515f91906003908110612d1c57612d1c6155ac565b60200260200101515f81518110612d3557612d356155ac565b6020908102919091018101516001600160a01b038481165f9081526001845260408082209284168252918452818120878252909352909120549091506001600160e01b0381161561051a576001600160a01b038084165f9081526001602090815260408083209386168352928152828220878352905290812055612dba838383612152565b50505050505050565b6060604082511015612de257505060408051602081019091525f815290565b5f60208301519050602060408451612dfa91906159c1565b612e049190615cf0565b811115612e2057505060408051602081019091525f8152919050565b600181016020026020840101915050919050565b5f81515f03612e4457505f919050565b50602001515f1a90565b612e5781613ccd565b612e765780604051630c89984b60e31b81526004016103169190615d0f565b50565b60605f612e868484613cfb565b9050808015612ea757505f3d1180612ea757505f846001600160a01b03163b115b15612ebc57612eb4613d0e565b9150506102b4565b8015612ee657604051639996b31560e01b81526001600160a01b0385166004820152602401610316565b3d15612ef957612ef4613d27565b612f12565b60405163d6bda27560e01b815260040160405180910390fd5b5092915050565b604080516080810182525f808252602082018190529181018290526060810191909152612f468383613d32565b82526040820152612f578284613d32565b6020830152606082015292915050565b5f80516020615ecd83398151915254600203612f9657604051633ee5aeb560e01b815260040160405180910390fd5b565b5f8085158415178187128286121817858414178015612fbd5786859250925050611ced565b505f85841315612fd1575092949193919260015b8386035f8112604c8213178015613004578215612ff6575f8994509450505050611ced565b885f94509450505050611ced565b600a82900a8981028a82828161301c5761301c615cdc565b0514613048578415613038575f8b965096505050505050611ced565b8a5f965096505050505050611ced565b841561305d578896509450611ced9350505050565b9550879450611ced9350505050565b5f805f61307884613d9b565b9092509050600182600381111561309157613091615d21565b141580156130b057505f8260038111156130ad576130ad615d21565b14155b156103bb57838260405163ee07877f60e01b8152600401610316929190615d35565b5f806001600160e01b038416601b0b60e085901d6130f1828287613e28565b9350935050505b9250929050565b60605f825167ffffffffffffffff81111561311c5761311c614d08565b604051908082528060200260200182016040528015613145578160200160208202803683370190505b5090505f80845111613157575f61315d565b83516001015b85516001010190505f8167ffffffffffffffff81111561317f5761317f614d08565b6040519080825280602002602001820160405280156131b257816020015b606081526020019060019003908161319d5790505b5090505f6131d6604080516002815233602082015230818301526060810190915290565b8282815181106131e8576131e86155ac565b60200260200101819052505f5b8751811015613245578180600101925050878181518110613218576132186155ac565b6020026020010151838381518110613232576132326155ac565b60209081029190910101526001016131f5565b508551156133d757808060010191505083828281518110613268576132686155ac565b60200260200101819052505f5b86518110156133d557613324878281518110613293576132936155ac565b60200260200101515f01516133016132cf8a85815181106132b6576132b66155ac565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b898481518110613313576133136155ac565b602002602001015160400151613f8e565b61334457604051630a57f30960e31b815260048101829052602401610316565b868181518110613356576133566155ac565b60200260200101515f01516001600160a01b03165f1b85828151811061337e5761337e6155ac565b60200260200101818152505081806001019250508681815181106133a4576133a46155ac565b6020026020010151602001518383815181106133c2576133c26155ac565b6020908102919091010152600101613275565b505b5095945050505050565b5f805f61307884613ffe565b5f805f805f6133fc878761405d565b9250925092505f8061340e85856140a0565b915091508183801561341d5750815b9650965050505050509250929050565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316613483578383151615613477573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b6040516323b872dd60e01b5f8181526001600160a01b038781166004528616602452604485905291602083606481808c5af1925060015f511483166134eb5783831516156134df573d5f823e3d81fd5b5f883b113d1516831692505b604052505f60605295945050505050565b5f8085158415178015613514575f92505f9150613611565b61351e8487615d6e565b91505f61352a88614178565b90505f61353687614178565b90505f61354383836141a6565b5090505f6f0785ee10d5da46d900f436a000000000821115613578576f0785ee10d5da46d900f436a000000000820491506025015b670de0b6b3a764000082111561359957670de0b6b3a7640000820491506012015b633b9aca008211156135b257633b9aca00820491506009015b6127108211156135c757612710820491506004015b81156135db57600a820491506001016135c7565b6135e58187615d6e565b95506136078b8a61360187876135fc87600a615e6d565b6141c2565b8961428e565b9097509550505050505b5094509492505050565b5f805f61362885856140a0565b9150915080158015613638575081155b1561366057604051638eba4d0760e01b81526004810186905260248101859052604401610316565b509392505050565b5f80613674848461432e565b909450925061368586868686613bcf565b9150915094509492505050565b5f80835f036136be57604051637a97930f60e01b81526004810187905260248101869052604401610316565b855f036136cf57505f905080611ced565b5f805f806136dd8a8a614383565b919b50995091506136ee8888614383565b919950975090505f6136ff8b614178565b90505f61370b8a614178565b90507f161bcca7119915b50764b4abe86529797775a5f1719510000000000000000000604c81831015613ad057841561376257507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b9050604b613aa8565b6f4b3b4ca85a86c47a098a22400000000083101561388e57678ac7230489e800008310156137f2576402540be4008310156137c057620186a08310156137b05750620186a090506005613a69565b506402540be4009050600a613a69565b655af3107a40008310156137df5750655af3107a40009050600e613a69565b50678ac7230489e8000090506013613a69565b6b204fce5e3e250261100000008310156138445769152d02c7e14af680000083101561382d575069152d02c7e14af680000090506017613a69565b506b204fce5e3e250261100000009050601c613a69565b6d314dc6448d9338c15b0a0000000083101561387357506d314dc6448d9338c15b0a0000000090506021613a69565b506f4b3b4ca85a86c47a098a22400000000090506026613a69565b780197d4df19d605767337e9f14d3eec8920e4000000000000008310156139865773af298d050e4395d69670b12b7f41000000000000831015613921577172cb5bd86321e38cb6ce6682e8000000000083101561390257507172cb5bd86321e38cb6ce6682e800000000009050602b613a69565b5073af298d050e4395d69670b12b7f4100000000000090506030613a69565b76010b46c6cdd6e3e0828f4db456ff0c8ea0000000000000831015613962575076010b46c6cdd6e3e0828f4db456ff0c8ea000000000000090506035613a69565b50780197d4df19d605767337e9f14d3eec8920e4000000000000009050603a613a69565b7c03b58e88c75313ec9d329eaaa18fb92f75215b17100000000000000000831015613a1c577a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000008310156139f457507a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000009050603f613a69565b507c03b58e88c75313ec9d329eaaa18fb92f75215b1710000000000000000090506044613a69565b7e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000831015613a6957507e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000905060495b818311613a7e57600a820491505f1901613a69565b815f03613aa8576040516305e51ecb60e01b8152600481018d9052602481018c9052604401610316565b85613ad0576040516305e51ecb60e01b8152600481018f9052602481018e9052604401610316565b80600160ff1b018d12613ae757808d039c50613b25565b600160ff1b9c90038c015f811315613b2557806001600160ff1b03038b13613b1257998a0199613b25565b5f80995099505050505050505050611ced565b5f808e128015613b3457505f8c135b15613b5557600160ff1b8e01808d13613b4d575f613b51565b808d035b9150505b8b818f01039750613b728f8e613b6c8887896141c2565b8b61428e565b90995097505f811315613bbc57604c811315613b9c575f809a509a50505050505050505050611ced565b80600a0a8981613bae57613bae615cdc565b059850885f03613bbc575f97505b50969850949650611ced95505050505050565b5f8085158415178015613bfb57865f03613bef5784849250925050611ced565b86869250925050611ced565b613c0587876145dd565b9097509550613c1485856145dd565b909550935085841315613c28579395929492935b838603604c811115613c41578787935093505050611ced565b80600a0a8681613c5357613c53615cdc565b0595505086850180881860ff90811c151589881890911c15168015613cbc57876001600160ff1b0303613ca35760405163d556b11160e01b8152600481018a905260248101899052604401610316565b600a968790059690980586019760019790970196613cc0565b8198505b5096979596505050505050565b5f600882511015613cdf57505f919050565b506008015167ffffffffffffffff1667ff0a89c674ee78741490565b5f805f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f80613d4f846060015185604001516126f290919063ffffffff16565b915083604001519050613d6f836040015183611b4c90919063ffffffff16565b156130f85782604001519150613d9284606001518361276f90919063ffffffff16565b90509250929050565b5f80613da5614626565b60405163b7bad1b160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb93899063b7bad1b19060240160408051808303815f875af1158015613dfb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e1f9190615e78565b91509150915091565b5f805f851215613e5557604051634a7d166b60e01b81526004810186905260248101859052604401610316565b845f03613e6757505f90506001611bfe565b8460ff8416850185811215613e995760405163d556b11160e01b81526004810188905260248101879052604401610316565b5f805f831215613ee557604c19831215613ebc575f809550955050505050611bfe565b825f03600a0a9150818481613ed357613ed3615cdc565b0495505084029091149150611bfe9050565b5f831315613f7e57604d831315613f225760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b82600a0a9150815f1981613f3857613f38615cdc565b04841115613f6c5760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b5091909102925060019150611bfe9050565b8360019550955050505050611bfe565b5f836001600160a01b03163b5f03613fec575f80613fac85856146b1565b5090925090505f816003811115613fc557613fc5615d21565b148015613fe35750856001600160a01b0316826001600160a01b0316145b925050506103bb565b613ff78484846146f7565b90506103bb565b5f80614008614626565b604051630782d7e160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb938990630782d7e1906024016040805180830381865afa158015613dfb573d5f803e3d5ffd5b5f808060ff841681036001600160ff1b0386111561408f57600a860460018201600a88065f1493509350935050614099565b8593509150600190505b9250925092565b5f601b83900b8314838382614104577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e10000000000000000008605156140e457620186a0860595506005850194505b8586601b0b146140ff57600a860595508460010194506140e4565b61411a565b855f0361411a57505f9250600191506130f89050565b848560030b1461415d575f85121561413a57505f92508291506130f89050565b60405163d556b11160e01b81526004810183905260248101829052604401610316565b50506001600160e01b03841660e084901b1791509250929050565b5f8082121561419d57600160ff1b82036141975750600160ff1b919050565b505f0390565b5090565b919050565b5f805f1983850993909202808410938190039390930393915050565b5f805f6141cf86866141a6565b91509150815f036141f3578381816141e9576141e9615cdc565b04925050506103bb565b8382106142245760405163362ced0960e11b8152600481018790526024810186905260448101859052606401610316565b5f84868809600186198101871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103025f82900382900490920185841190960395909502919093039390930492909217029150509392505050565b5f805f858718121561430a576001600160ff1b038411156142f7576142bb6001600160ff1b036001615553565b84036142cf5750600160ff1b905081611ced565b6142da600a85615cf0565b6142e390615eb8565b6142ee846001615d6e565b91509150611ced565b61430084615eb8565b8391509150611ced565b6001600160ff1b03841115614324576142e3600a85615cf0565b5082905081611ced565b5f80600160ff1b8403614379576001600160ff1b03830361436c5760405163d556b11160e01b81526004810185905260248101849052604401610316565b600a840593508260010192505b50505f9190910391565b5f805f845f0361439b57505f91508190506001614099565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85055f03614588576f4b3b4ca85a86c47a098a22400000000085051580156143fd57507f80000000000000000000000000000000000000000000000000000000000000268412155b1561441e576f4b3b4ca85a86c47a098a224000000000850294506026840393505b7728c87cb5c89a2571ebfdcb54864ada834a00000000000000850515801561446657507f80000000000000000000000000000000000000000000000000000000000000138412155b1561447f57678ac7230489e80000850294506013840393505b7b097edd871cfda3a5697758bf0e3cbb5ac5741c64000000000000000085051580156144cb57507f800000000000000000000000000000000000000000000000000000000000000a8412155b156144e1576402540be40085029450600a840393505b7e3899162693736ac531a5a58f1fbb4b746504382ca7e4000000000000000000850515801561453057507f80000000000000000000000000000000000000000000000000000000000000028412155b15614546576064850294506002840393506144e1565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b850515801561457657506001600160ff1b018412155b1561458857600a850294506001840393505b600a808602908105861480156145a557506001600160ff1b018512155b156145b4578095506001850394505b50939492935050507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b8305151590565b5f805f805f6145ec8787614383565b9250925092508061461a576040516305e51ecb60e01b81526004810188905260248101879052604401610316565b50909590945092505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b158061467d575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b15612f96576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610316565b5f805f83516041036146e8576020840151604085015160608601515f1a6146da88828585614748565b955095509550505050614099565b505081515f9150600290614099565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561478157505f91506003905082614806565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156147d2573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166147fd57505f925060019150829050614806565b92505f91508190505b9450945094915050565b604051806080016040528061482361483c565b81526020015f81526020015f8152602001606081525090565b6040518060a001604052805f6001600160a01b0316815260200161488a60405180606001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b8152606060208201819052604082018190525f91015290565b6040518060e001604052806148b661483c565b81526020015f81526020015f80191681526020015f8019168152602001606081526020015f8152602001606081525090565b5f602082840312156148f8575f80fd5b81356001600160e01b0319811681146103bb575f80fd5b5f8083601f84011261491f575f80fd5b50813567ffffffffffffffff811115614936575f80fd5b6020830191508360208260051b85010111156130f8575f80fd5b5f805f60408486031215614962575f80fd5b833567ffffffffffffffff80821115614979575f80fd5b9085019060a0828803121561498c575f80fd5b909350602085013590808211156149a1575f80fd5b506149ae8682870161490f565b9497909650939450505050565b5f602082840312156149cb575f80fd5b5035919050565b6001600160a01b0381168114612e76575f80fd5b80356141a1816149d2565b5f805f805f60808688031215614a05575f80fd5b8535614a10816149d2565b94506020860135935060408601359250606086013567ffffffffffffffff811115614a39575f80fd5b614a458882890161490f565b969995985093965092949392505050565b5f805f60608486031215614a68575f80fd5b8335614a73816149d2565b92506020840135614a83816149d2565b929592945050506040919091013590565b5f805f805f60808688031215614aa8575f80fd5b8535614ab3816149d2565b94506020860135614ac3816149d2565b935060408601359250606086013567ffffffffffffffff80821115614ae6575f80fd5b818801915088601f830112614af9575f80fd5b813581811115614b07575f80fd5b896020828501011115614b18575f80fd5b9699959850939650602001949392505050565b5f60208284031215614b3b575f80fd5b81356103bb816149d2565b5f60c08284031215614b56575f80fd5b50919050565b5f60208284031215614b6c575f80fd5b813567ffffffffffffffff811115614b82575f80fd5b61052d84828501614b46565b5f805f60408486031215614ba0575f80fd5b833567ffffffffffffffff80821115614bb7575f80fd5b614bc387838801614b46565b945060208601359150808211156149a1575f80fd5b5f60208284031215614be8575f80fd5b813567ffffffffffffffff811115614bfe575f80fd5b8201608081850312156103bb575f80fd5b5f8060208385031215614c20575f80fd5b823567ffffffffffffffff811115614c36575f80fd5b614c428582860161490f565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614cd157603f19888603018452614cbf858351614c4e565b94509285019290850190600101614ca3565b5092979650505050505050565b5f8060408385031215614cef575f80fd5b8235614cfa816149d2565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b60405290565b6040805190810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b60405160a0810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b604051601f8201601f1916810167ffffffffffffffff81118282101715614db457614db4614d08565b604052919050565b5f82601f830112614dcb575f80fd5b813567ffffffffffffffff811115614de557614de5614d08565b614df8601f8201601f1916602001614d8b565b818152846020838601011115614e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608284031215614e38575f80fd5b614e40614d1c565b90508135614e4d816149d2565b81526020820135614e5d816149d2565b6020820152604082013567ffffffffffffffff811115614e7b575f80fd5b614e8784828501614dbc565b60408301525092915050565b5f67ffffffffffffffff821115614eac57614eac614d08565b5060051b60200190565b5f60408284031215614ec6575f80fd5b614ece614d45565b90508135614edb816149d2565b808252506020820135602082015292915050565b5f82601f830112614efe575f80fd5b81356020614f13614f0e83614e93565b614d8b565b8083825260208201915060208460061b870101935086841115614f34575f80fd5b602086015b84811015614f5957614f4b8882614eb6565b835291830191604001614f39565b509695505050505050565b5f60a08284031215614f74575f80fd5b614f7c614d68565b9050614f87826149e6565b8152602082013567ffffffffffffffff80821115614fa3575f80fd5b614faf85838601614e28565b60208401526040840135915080821115614fc7575f80fd5b614fd385838601614eef565b60408401526060840135915080821115614feb575f80fd5b50614ff884828501614eef565b6060830152506080820135608082015292915050565b5f61501b614f0e84614e93565b8381529050602080820190600585811b850187811115615039575f80fd5b855b8181101561512657803567ffffffffffffffff8082111561505a575f80fd5b908801906060828c03121561506d575f80fd5b615075614d1c565b8235615080816149d2565b81528287013582811115615092575f80fd5b8301601f81018d136150a2575f80fd5b80356150b0614f0e82614e93565b81815290881b8201890190898101908f8311156150cb575f80fd5b928a01925b828410156150e95783358252928a0192908a01906150d0565b848b01525060409150508381013583811115615103575f80fd5b61510f8e828701614dbc565b91830191909152508752505093830193830161503b565b50505050509392505050565b5f82601f830112615141575f80fd5b6103bb8383356020850161500e565b5f805f805f6101408688031215615165575f80fd5b853567ffffffffffffffff8082111561517c575f80fd5b61518889838a01614f64565b9650602088013591508082111561519d575f80fd5b6151a989838a01614f64565b95506151b88960408a01614b46565b94506101008801359150808211156151ce575f80fd5b6151da89838a01615132565b93506101208801359150808211156151f0575f80fd5b506151fd88828901615132565b9150509295509295909350565b5f6102b43683614f64565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f8135615249816149d2565b6001600160a01b039081168452602083013590615265826149d2565b166020840152604082013536839003601e19018112615282575f80fd5b820160208101903567ffffffffffffffff81111561529e575f80fd5b8036038213156152ac575f80fd5b606060408601526152c1606086018284615215565b95945050505050565b5f808335601e198436030181126152df575f80fd5b830160208101925035905067ffffffffffffffff8111156152fe575f80fd5b8060061b36038213156130f8575f80fd5b8183525f60208085019450825f5b85811015615355578135615330816149d2565b6001600160a01b0316875281830135838801526040968701969091019060010161531d565b509495945050505050565b5f6001600160a01b038086168352846020840152606060408401528335615386816149d2565b166060830152602083013536849003605e190181126153a3575f80fd5b60a060808401526153ba610100840185830161523d565b90506153c960408501856152ca565b605f19808685030160a08701526153e184838561530f565b93506153f060608801886152ca565b93509150808685030160c08701525061540a83838361530f565b92505050608084013560e084015280915050949350505050565b5f615431614f0e84614e93565b80848252602080830192508560051b85013681111561544e575f80fd5b855b818110156154d857803567ffffffffffffffff8082111561546f575f80fd5b818901915060408236031215615483575f80fd5b61548b614d45565b823582811115615499575f80fd5b6154a536828601614e28565b82525085830135828111156154b8575f80fd5b6154c436828601615132565b828801525087525050938201938201615450565b50919695505050505050565b5f6001600160a01b03808916835280881660208401525085604083015284606083015260a0608083015261551c60a083018486615215565b98975050505050505050565b5f60208284031215615538575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102b4576102b461553f565b5f808335601e1984360301811261557b575f80fd5b83018035915067ffffffffffffffff821115615595575f80fd5b6020019150600581901b36038213156130f8575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e198336030181126155d4575f80fd5b9190910192915050565b5f8235609e198336030181126155d4575f80fd5b5f808335601e19843603018112615607575f80fd5b83018035915067ffffffffffffffff821115615621575f80fd5b6020019150600681901b36038213156130f8575f80fd5b5f60808236031215615648575f80fd5b6040516080810167ffffffffffffffff828210818311171561566c5761566c614d08565b816040528435915080821115615680575f80fd5b61568c36838701614f64565b8352602085013560208401526040850135604084015260608501359150808211156156b5575f80fd5b506156c236828601615132565b60608301525092915050565b5f602082840312156156de575f80fd5b813580151581146103bb575f80fd5b5f815180845260208085019450602084015f5b8381101561535557815180516001600160a01b031688528301518388015260409096019590820190600101615700565b5f6001600160a01b03808351168452602083015160a060208601528181511660a08601528160208201511660c08601526040810151915050606060e085015261577d610100850182614c4e565b90506040830151848203604086015261579682826156ed565b915050606083015184820360608601526157b082826156ed565b915050608083015160808501528091505092915050565b5f815180845260208085019450602084015f5b83811015615355578151875295820195908201906001016157da565b5f6001600160a01b03808716835260206080818501528651608080860152615822610100860182615730565b90508188015160a086015260408089015160c08701526060808a0151607f198885030160e08901528381518086528686019150868160051b87010187840193505f5b828110156158be57601f1988830301845284518a815116835289810151878b850152615892888501826157c7565b91890151848303858b01529190506158aa8183614c4e565b968b0196958b019593505050600101615864565b5080995050505050505050505083604083015282606083015295945050505050565b5f808335601e198436030181126158f5575f80fd5b83018035915067ffffffffffffffff82111561590f575f80fd5b6020019150368190038213156130f8575f80fd5b5f8235605e198336030181126155d4575f80fd5b5f6102b43683614e28565b5f60408284031215615952575f80fd5b6103bb8383614eb6565b6001600160a01b0384168152826020820152606060408201525f6152c16060830184615730565b6001600160a01b0385168152836020820152606060408201525f6159ab606083018486615215565b9695505050505050565b5f6103bb36848461500e565b818103818111156102b4576102b461553f565b828482375f8382015f815283518060208601835e5f910190815295945050505050565b5f6101206001600160a01b0387168352806020840152615a1981840187615730565b90508281036040840152615a2d8186615730565b9150508235606083015260208301356080830152604083013560a0830152606083013560c0830152608083013560e083015260a083013561010083015295945050505050565b602081525f6103bb6020830184615730565b5f60018201615a9657615a9661553f565b5060010190565b5f8282518085526020808601955060208260051b840101602086015f5b84811015615ae857601f19868403018952615ad68383516157c7565b98840198925090830190600101615aba565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e06060840152615b2e610100840182614c4e565b9050606084015160808401526080840151601f19808584030160a0860152615b568383615a9d565b925060a08601519150808584030160c0860152615b7383836157c7565b925060c08601519150808584030160e0860152506152c182826157c7565b5f82601f830112615ba0575f80fd5b81516020615bb0614f0e83614e93565b8083825260208201915060208460051b870101935086841115615bd1575f80fd5b602086015b84811015614f595780518352918301918301615bd6565b5f8060408385031215615bfe575f80fd5b825167ffffffffffffffff80821115615c15575f80fd5b818501915085601f830112615c28575f80fd5b81516020615c38614f0e83614e93565b82815260059290921b84018101918181019089841115615c56575f80fd5b948201945b83861015615c7457855182529482019490820190615c5b565b91880151919650909350505080821115615c8c575f80fd5b50615c9985828601615b91565b9150509250929050565b828152604060208201525f61052d60408301846157c7565b6001600160a01b0383168152604060208201525f61052d6040830184615a9d565b634e487b7160e01b5f52601260045260245ffd5b5f82615d0a57634e487b7160e01b5f52601260045260245ffd5b500490565b602081525f6103bb6020830184614c4e565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040810160048310615d6157634e487b7160e01b5f52602160045260245ffd5b8260208301529392505050565b8082018281125f8312801582168215821617156114ac576114ac61553f565b600181815b80851115615dc757815f1904821115615dad57615dad61553f565b80851615615dba57918102915b93841c9390800290615d92565b509250929050565b5f82615ddd575060016102b4565b81615de957505f6102b4565b8160018114615dff5760028114615e0957615e25565b60019150506102b4565b60ff841115615e1a57615e1a61553f565b50506001821b6102b4565b5060208310610133831016604e8410600b8410161715615e48575081810a6102b4565b615e528383615d8d565b805f1904821115615e6557615e6561553f565b029392505050565b5f6103bb8383615dcf565b5f8060408385031215615e89575f80fd5b825160048110615e97575f80fd5b602084015190925060ff81168114615ead575f80fd5b809150509250929050565b5f600160ff1b82016141975761419761553f56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00", + "object": "0x6080604052348015600e575f80fd5b5060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055616019806100405f395ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c8063613255ab11610093578063ac9650d811610063578063ac9650d81461022b578063d7e442ec1461024b578063d9d98ce41461025e578063fa50118214610271575f80fd5b8063613255ab146101ad57806369c72856146101c0578063709fb8a5146101e85780639235084d146101fb575f80fd5b80632fbc4ba0116100ce5780632fbc4ba01461015157806341d1514f146101665780635cffe9de14610187578063607461191461019a575f80fd5b806301ffc9a7146100f45780631f69cb751461011c5780632cb77e9f1461012f575b5f80fd5b610107610102366004614a14565b610284565b60405190151581526020015b60405180910390f35b61010761012a366004614a7c565b6102ba565b61010761013d366004614ae7565b5f9081526020819052604090205460011490565b61016461015f366004614b1d565b6103c2565b005b610179610174366004614b82565b610521565b604051908152602001610113565b610107610195366004614bc0565b610535565b6101646101a8366004614b1d565b610635565b6101796101bb366004614c57565b6107c8565b6101d36101ce366004614c88565b610830565b60408051928352602083019190915201610113565b6101076101f6366004614cba565b610fc9565b61020e610209366004614d04565b61130c565b604080519315158452602084019290925290820152606001610113565b61023e610239366004614d3b565b6113ce565b6040516101139190614da8565b610164610259366004614d3b565b6114b4565b61017961026c366004614e0a565b61150e565b61016461027f36600461527c565b6115a8565b5f6001600160e01b0319821663e414309160e01b14806102b457506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6102c3611a9a565b6102d06020850185614c57565b6001600160a01b0316336001600160a01b03161461031f576102f56020850185614c57565b6040516335252be360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b5f61033161032c86615336565b611ab5565b5f818152602081905260409020549091505f19016103a4575f818152602081905260408082209190915551600192507f09d18501db0080ca2d6cd7c17fa7255daff4b2d503ea93b76ff68b6752ea8e63906103919033908490899061548c565b60405180910390a16103a4818585611ae4565b506103bb60015f80516020615ff983398151915255565b9392505050565b6103ca611a9a565b3385856103d8838383611b1b565b6103e2865f611b4c565b610417576040516306dde9c360e41b81523360048201526001600160a01b038916602482015260448101889052606401610316565b5f80610424338b8a611b86565b604080513381526001600160a01b038e1660208201529081018c90526060810183905291935091507f7f9dfa19cf1cc2f806f2f860fbc9c056b601fb1afc0e9b843dfe5c63616268e69060800160405180910390a15f80610487338d8d8d611cbe565b909250905087156104fd5760408051600581526001600160a01b038e1660208201528082018d9052606081018490526080810183905260ff851660a082015260c081019091526104fd906104ee905b60408051600181526020810192909252818101905290565b6104f88a8c615550565b611dae565b5050505050505061051a60015f80516020615ff983398151915255565b5050505050565b5f61052d848484611f7c565b949350505050565b5f61054a6001600160a01b0386168786612106565b6040516323e30c8b60e01b81525f906001600160a01b038816906323e30c8b906105829033908a908a9087908b908b90600401615610565b6020604051808303815f875af115801561059e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c29190615654565b90507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9811461060757604051630b6c58a960e31b815260048101829052602401610316565b61062887306106165f8961567f565b6001600160a01b038a1692919061213b565b5060019695505050505050565b61063d611a9a565b33858561064b838383611b1b565b5f8080806106598a82611b4c565b61068d57604051623a3a4d60e21b81523360048201526001600160a01b038d166024820152604481018c9052606401610316565b5f610699338e8e611f7c565b90506106a58b82612177565b94506106b3338e8e88612193565b90935091505f6106c4338f8861220a565b80965081925050507f8045c25080b0868951141ed0a91720bcad09a8364a2b3109ee1fd49c1f0bc8b8338f8f8f8a86604051610736969594939291906001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b60405180910390a1505060408051600681526001600160a01b038e1660208201528082018d9052606081018490526080810183905260a081018c905260ff851660c0820152600160e08201908152610100820182905261012082019092529089156107a9576107a9816104f88c8e615550565b50505050505050505061051a60015f80516020615ff983398151915255565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa15801561080c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b49190615654565b5f8061083a611a9a565b6108476080840184615692565b90505f0361086857604051639c95219f60e01b815260040160405180910390fd5b61087061493c565b610878614968565b5f60405180606001604052808780608001906108949190615692565b5f8181106108a4576108a46156d8565b90506020028101906108b691906156ec565b6108c0908061570a565b6108ce90604081019061571e565b6108db60808b018b615692565b5f8181106108eb576108eb6156d8565b90506020028101906108fd91906156ec565b60200135818110610910576109106156d8565b6109269260206040909202019081019150614c57565b6001600160a01b031681526020016109416080890189615692565b5f818110610951576109516156d8565b905060200281019061096391906156ec565b61096d908061570a565b61097b90606081019061571e565b61098860808b018b615692565b5f818110610998576109986156d8565b90506020028101906109aa91906156ec565b604001358181106109bd576109bd6156d8565b6109d39260206040909202019081019150614c57565b6001600160a01b03168152602088810135910152905060605f6109f96080890189615692565b604080516001909201602002820181528501519093505f9250610a1d915082611b4c565b610a3a5760405163315f9e2360e21b815260040160405180910390fd5b5f5b610a4960808a018a615692565b905081108015610a6357506040840151610a63905f611b4c565b15610e7157610a7560808a018a615692565b82818110610a8557610a856156d8565b9050602002810190610a9791906156ec565b610aa090615764565b9550855f01519450835f01516001600160a01b03168560400151876020015181518110610acf57610acf6156d8565b60200260200101515f01516001600160a01b0316141580610b2a575083602001516001600160a01b03168560600151876040015181518110610b1357610b136156d8565b60200260200101515f01516001600160a01b031614155b15610b485760405163936bb5ad60e01b815260040160405180910390fd5b610b5b85876020015188604001516122e7565b5f610b6586611ab5565b5f81815260208190526040902054909150610bca578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a1610e68565b5f610c278789602001518a60400151338c606001515f67ffffffffffffffff811115610bf857610bf8614e34565b604051908082528060200260200182016040528015610c21578160200160208202803683370190505b50612359565b90505f610c458c604001358360600151611b4c90919063ffffffff16565b15610c9b578751604080513381526001600160a01b03909216602083015281018490527fe3151dc8cb7a54ffc4baabd28c1f241c94d510b5e5b502491ac3cad6c16316d5906060015b60405180910390a1610e5a565b6040820151610caa905f611b4c565b1580610cc257506060820151610cc0905f611b4c565b155b15610d0f578751604080513381526001600160a01b03909216602083015281018490527f500b713857325f9e6dcb52ae832eca9109d107ed1aae9cb4928b4c1e13f051aa90606001610c8e565b600190505f808d6060016020810190610d2891906157fa565b15610d6e576040808a015190850151610d4091612177565b6060850151909250610d52908361281e565b60408a0151909150610d64908361286b565b60408a0152610dd5565b5f610d8a8560400151866060015161281e90919063ffffffff16565b9050610da38a604001518261217790919063ffffffff16565b9150610dbc85606001518361289b90919063ffffffff16565b60408b0151909350610dce908361286b565b60408b0152505b610ddf8c826128cb565b9b50610deb8d836128cb565b9c50610df782856128fb565b610e0181856129bc565b7f194f1feb3b4d7076a2c272e774e792e0c48bb8c7aa1a9a3671c1cd6da9e6b4c1338c8484604051610e369493929190615922565b60405180910390a187516001018089526020028801849052610e5784612b68565b50505b8480610e635750805b945050505b50600101610a3c565b505f610e8360808a0160608b016157fa565b610e8d5786610e8f565b875b9050610e9c818a35612dab565b15610ec45760405163573b6f4160e01b81528935600482015260248101829052604401610316565b50610ed43384602001518961220a565b505f9050610ee560a08a018a615a0c565b9050118015610ef15750805b15610f635760208301518351339163691f9ed7918a8a610f1460a08f018f615a0c565b6040518763ffffffff1660e01b8152600401610f3596959493929190615610565b5f604051808303815f87803b158015610f4c575f80fd5b505af1158015610f5e573d5f803e3d5ffd5b505050505b610f7133845f015188611b86565b50505f5b8251811015610fa857610fa0838281518110610f9357610f936156d8565b6020026020010151612de5565b600101610f75565b505050505050610fc460015f80516020615ff983398151915255565b915091565b5f610fd2611a9a565b5f61102f61102a610fe38780615a4f565b610ff1906040810190615a0c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612eef92505050565b612f60565b90505f811161105157604051632cff108b60e21b815260040160405180910390fd5b6001811161107257604051633c8270bd60e21b815260040160405180910390fd5b61107f602086018661571e565b90505f036110a057604051636c44ef8f60e01b815260040160405180910390fd5b6110ad604086018661571e565b90505f036110ce5760405163540e5f0b60e01b815260040160405180910390fd5b6040805160a081019091523381525f90602081016110ec8880615a4f565b6110f590615a63565b815260200187806020019061110a919061571e565b808060200260200160405190810160405280939291908181526020015f905b828210156111555761114660408302860136819003810190615a6e565b81526020019060010190611129565b505050918352505060200161116d604089018961571e565b808060200260200160405190810160405280939291908181526020015f905b828210156111b8576111a960408302860136819003810190615a6e565b8152602001906001019061118c565b50505050508152602001876060013581525090505f6111d682611ab5565b5f818152602081905260409020549091501580156112f1575f828152602081905260409081902060019055835190517f87491344dfbcf91f6cbbc610cbbeedc85313d37a02df0c93527f7ea5f8db717f916112349185908790615a88565b60405180910390a15f61124a60a08a018a615a0c565b905011156112e65761129b61126260a08a018a615a0c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612f7a92505050565b82517fd46c2c56b35c8210e9e712ec3f02242d5fc90187c0ac8ed80cc33626846ec36990836112cd60a08c018c615a0c565b6040516112dd9493929190615aaf565b60405180910390a15b6112f1828888611ae4565b93505050506103bb60015f80516020615ff983398151915255565b5f80808061132661131d868061570a565b61032c90615336565b5f8181526020819052604090205490915060011461134d57505f92508291508190506113c7565b61137261135a868061570a565b61136390615336565b866020013587604001356122e7565b5f6113b0611380878061570a565b61138990615336565b60208801356040890135336113a160608c018c615692565b6113aa91615ae1565b5f610bf8565b905060018160400151826060015194509450945050505b9193909250565b604080515f8152602081019091526060908267ffffffffffffffff8111156113f8576113f8614e34565b60405190808252806020026020018201604052801561142b57816020015b60608152602001906001900390816114165790505b5091505f5b838110156114ac576114873086868481811061144e5761144e6156d8565b90506020028101906114609190615a0c565b8560405160200161147393929190615b00565b604051602081830303815290604052612fa5565b838281518110611499576114996156d8565b6020908102919091010152600101611430565b505092915050565b6114bc611a9a565b604080515f808252602082019092526114f4916114e9565b60608152602001906001900390816114d45790505b506104f88385615550565b61150a60015f80516020615ff983398151915255565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa158015611552573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115769190615654565b5f036115a057604051633c5bf76960e21b81526001600160a01b0384166004820152602401610316565b505f92915050565b6115b0611a9a565b835185516001600160a01b039182169116036115df57604051630a98f1f360e21b815260040160405180910390fd5b83604001518360400135815181106115f9576115f96156d8565b60200260200101515f01516001600160a01b03168560600151846020013581518110611627576116276156d8565b60200260200101515f01516001600160a01b03161415806116a0575060408501518051843590811061165b5761165b6156d8565b60200260200101515f01516001600160a01b03168460600151846060013581518110611689576116896156d8565b60200260200101515f01516001600160a01b031614155b156116be5760405163936bb5ad60e01b815260040160405180910390fd5b84606001518360200135815181106116d8576116d86156d8565b60200260200101515f01516001600160a01b03168560400151845f013581518110611705576117056156d8565b60200260200101515f01516001600160a01b03160361173757604051631cd2f1c760e21b815260040160405180910390fd5b5f61174186611ab5565b5f818152602081905260409020549091506117a7578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a150611a84565b5f6117b186611ab5565b5f81815260208190526040902054909150611818578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a15050611a84565b7f6fa7f4c28634b0a9d6831401c45ae468195fb63aed07308935c35374ff5d9e393388888860405161184d9493929190615b23565b60405180910390a1505083515f906118719087908635906020880135908686610bf8565b90505f6118a086866040013587606001358a5f0151885f67ffffffffffffffff811115610bf857610bf8614e34565b90505f6118ad8383613045565b90506118bc815f0151846128fb565b6118ca8160200151836128fb565b6118d88160400151846129bc565b6118e68160600151836129bc565b6118ef83612de5565b6118f882612de5565b606081015181515f9161190b919061286b565b90505f6119298360400151846020015161286b90919063ffffffff16565b9050611935825f612dab565b806119455750611945815f612dab565b1561196357604051630d86822160e01b815260040160405180910390fd5b611997338b606001518a6020013581518110611981576119816156d8565b60200260200101515f01518a6080013585611cbe565b50506119cd338a606001518a60600135815181106119b7576119b76156d8565b60200260200101515f01518a60a0013584611cbe565b5050604080513381528451602080830191909152850151818301529084015160608083019190915284015160808201527fd9fa84dd790c969daa5c33d8050dc06b4a9b59d5b42e2be5f5e8ae20447f618d925060a001905060405180910390a1611a3683612b68565b611a3f82612b68565b80516001600160e01b0316158015611a62575060208101516001600160e01b0316155b15611a80576040516321badf1f60e01b815260040160405180910390fd5b5050505b61051a60015f80516020615ff983398151915255565b611aa2613093565b60025f80516020615ff983398151915255565b5f81604051602001611ac79190615b9f565b604051602081830303815290604052805190602001209050919050565b604080516002815260208101859052338183015260608101909152611b1690611b0c906104d6565b6104f88385615550565b505050565b80611b16576040516305dbdfd960e41b81526001600160a01b03808516600483015283166024820152604401610316565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d611b7a848484846130c4565b12979650505050505050565b5f805f611b9285613198565b9050611b9e845f612dab565b15611bbc57604051632eaefac360e21b815260040160405180910390fd5b6001600160a01b038087165f90815260026020908152604080832093891683529290529081205490611bee868361286b565b90505f80611bfc8382611b4c565b15611c62575f611c0c84876131fe565b909350905080611c2257611c1f83615bb1565b92505b5f611c2d8a886131fe565b50905080611c3c85600161567f565b1015611c4a57809350600192505b611c5f6001600160a01b038c168d308761213b565b50505b5f611c6d838761322b565b50905081611c8457611c7f818561286b565b611c86565b845b6001600160a01b03808d165f908152600260209081526040808320938f1683529290522055509095509293505050505b935093915050565b5f80611cca8382612dab565b15611ceb5760405163793a8f5560e01b815260048101849052602401610316565b83611d0957611cfb86868561220a565b505f9250829150611da59050565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611d4382866128cb565b9050611d4f815f612dab565b15611d705760405163c5e12af560e01b815260048101829052602401610316565b6001600160a01b038089165f908152600160209081526040808320938b16835292815282822089835290522081905590925090505b94509492505050565b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b8651811015611f7257868181518110611e1557611e156156d8565b602002602001015193505f845f015160400151511115611f6a575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001611e8d8d8a6020015161326b565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401611eb89190615c21565b5f60405180830381865afa158015611ed2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611ef99190810190615d19565b9150505f81511115611f685784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490611f3a908a908590600401615dcf565b5f604051808303815f87803b158015611f51575f80fd5b505af1158015611f63573d5f803e3d5ffd5b505050505b505b600101611dfa565b5050505050505050565b5f8115611fb657506001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546103bb565b5f611fc08461354d565b6040516370a0823160e01b81526001600160a01b0387811660048301529192505f9161203891908716906370a0823190602401602060405180830381865afa15801561200e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120329190615654565b8361322b565b50604051636eb1769f60e11b81526001600160a01b0388811660048301523060248301529192505f916120b7919088169063dd62ed3e90604401602060405180830381865afa15801561208d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120b19190615654565b8461322b565b506001600160a01b038089165f908152600160209081526040808320938b168352928152828220828052905220549091506120fc906120f68484612177565b906128cb565b93505050506103bb565b6121138383836001613559565b611b1657604051635274afe760e01b81526001600160a01b0384166004820152602401610316565b6121498484848460016135bb565b61217157604051635274afe760e01b81526001600160a01b0385166004820152602401610316565b50505050565b5f6121828383612dab565b61218c57816103bb565b5090919050565b5f8061219f8382612dab565b156121c05760405163793a8f5560e01b815260048101849052602401610316565b836121d057611cfb868685611b86565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611d43828661286b565b5f805f61221685613198565b9050612222845f612dab565b1561224057604051632d1671a360e11b815260040160405180910390fd5b6001600160a01b038087165f9081526002602090815260408083209389168352929052908120546122729086906128cb565b90505f61227f82846131fe565b5090505f61228d828561322b565b50905061229a838261286b565b6001600160a01b03808b165f908152600260209081526040808320938d168352929052205581156122d9576122d96001600160a01b0389168a84612106565b509791965090945050505050565b826060015181815181106122fd576122fd6156d8565b60200260200101515f01516001600160a01b031683604001518381518110612327576123276156d8565b60200260200101515f01516001600160a01b031603611b1657604051631cd2f1c760e21b815260040160405180910390fd5b6123616149cf565b60408051600480825260a082019092526060915f9190816020015b606081526020019060019003908161237c5790505090506123d161239f8a611ab5565b8a51604080516003815260208101939093526001600160a01b0391821683820152908916606083015260808201905290565b8160018003815181106123e6576123e66156d8565b60200260200101819052505f61241b8a604001518a8151811061240b5761240b6156d8565b60200260200101515f015161354d565b90505f61246d8b5f01518c604001518c8151811061243b5761243b6156d8565b60200260200101515f01518d604001518d8151811061245c5761245c6156d8565b602002602001015160200151611f7c565b90506124fc8b604001518b81518110612488576124886156d8565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d604001518d815181106124ba576124ba6156d8565b602002602001015160200151845f801b60408051600581526020810196909652858101949094526060850192909252608084015260a083015260c08201905290565b83600160030381518110612512576125126156d8565b602002602001018190525050505f6125398a60600151898151811061240b5761240b6156d8565b90505f61257a8b5f01518c606001518b81518110612559576125596156d8565b60200260200101515f01518d606001518c8151811061245c5761245c6156d8565b90506125c78b606001518a81518110612595576125956156d8565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d606001518c815181106124ba576124ba6156d8565b836001600403815181106125dd576125dd6156d8565b602002602001018190525050506125f4818661326b565b9150505f885f01516001600160a01b031690505f808a602001515f01516001600160a01b031663d04dfe236040518060e001604052808e60200151602001516001600160a01b0316815260200161265487305f9182526020526040902090565b81526020018e602001516040015181526020015f81526020018781526020015f67ffffffffffffffff81111561268c5761268c614e34565b6040519080825280602002602001820160405280156126b5578160200160208202803683370190505b508152602001898152506040518263ffffffff1660e01b81526004016126db9190615c21565b5f60405180830381865afa1580156126f5573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261271c9190810190615d19565b91509150600282511015612748578151604051630fbb8e5560e21b815260040161031691815260200190565b60208201516040830151855161279c908790600490811061276b5761276b6156d8565b6020026020010151600381518110612785576127856156d8565b60200260200101518261217790919063ffffffff16565b60408051600281526020810183905280820185905260608101909152909150866002815181106127ce576127ce6156d8565b60200260200101819052506040518060e001604052808e81526020018c81526020018281526020018381526020018781526020018681526020018481525096505050505050509695505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613628565b915091505f61285d8383613747565b9a9950505050505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613794565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e868686866137be565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613cfb565b818160800151600481518110612913576129136156d8565b602002602001015160048151811061292d5761292d6156d8565b602002602001018181525050612171815f01515f0151826080015160048151811061295a5761295a6156d8565b60200260200101515f81518110612973576129736156d8565b60200260200101515f1c8360800151600481518110612994576129946156d8565b60200260200101516002815181106129ae576129ae6156d8565b602002602001015185612193565b8181608001516003815181106129d4576129d46156d8565b60200260200101516004815181106129ee576129ee6156d8565b6020908102919091010152805151608082015180515f91906003908110612a1757612a176156d8565b60200260200101515f81518110612a3057612a306156d8565b60200260200101515f1c90505f8360800151600381518110612a5457612a546156d8565b6020026020010151600281518110612a6e57612a6e6156d8565b602002602001015190505f801b8103612b1557612a8b855f612dab565b15612aac5760405163793a8f5560e01b815260048101869052602401610316565b6001600160a01b038084165f908152600160209081526040808320938616835292815282822084835290522054612ae390866128cb565b6001600160a01b038085165f908152600160209081526040808320938716835292815282822085835290522055612b24565b612b2183838388611cbe565b50505b7f4cb6e22a3e7e651d7cf0376cff48f20f5007a54147777865be7f5f6c38c50f4a338560800151604051612b59929190615de7565b60405180910390a15050505050565b60c08101515115612be2578051602090810151015160a082015160c083015160405163012c676d60e21b81526001600160a01b03909316926304b19db492612bb4929091600401615dcf565b5f604051808303815f87803b158015612bcb575f80fd5b505af1158015612bdd573d5f803e3d5ffd5b505050505b5f815f0151602001515f01516001600160a01b031663d04dfe236040518060e00160405280855f015160200151602001516001600160a01b03168152602001612c388660a00151305f9182526020526040902090565b8152602001855f01516020015160400151815260200160018152602001856080015181526020015f67ffffffffffffffff811115612c7857612c78614e34565b604051908082528060200260200182016040528015612ca1578160200160208202803683370190505b5081526020015f604051908082528060200260200182016040528015612cd1578160200160208202803683370190505b508152506040518263ffffffff1660e01b8152600401612cf19190615c21565b5f60405180830381865afa158015612d0b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612d329190810190615d19565b9150505f8151111561150a578151602090810151015160a083015160405163012c676d60e21b81526001600160a01b03909216916304b19db491612d7a918590600401615dcf565b5f604051808303815f87803b158015612d91575f80fd5b505af1158015612da3573d5f803e3d5ffd5b505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d612dd9848484846130c4565b13979650505050505050565b5f8160800151600381518110612dfd57612dfd6156d8565b6020026020010151600281518110612e1757612e176156d8565b602002602001015190505f801b810361150a57815151608083015180515f91906003908110612e4857612e486156d8565b60200260200101515f81518110612e6157612e616156d8565b6020908102919091018101516001600160a01b038481165f9081526001845260408082209284168252918452818120878252909352909120549091506001600160e01b0381161561051a576001600160a01b038084165f9081526001602090815260408083209386168352928152828220878352905290812055612ee683838361220a565b50505050505050565b6060604082511015612f0e57505060408051602081019091525f815290565b5f60208301519050602060408451612f269190615aed565b612f309190615e1c565b811115612f4c57505060408051602081019091525f8152919050565b600181016020026020840101915050919050565b5f81515f03612f7057505f919050565b50602001515f1a90565b612f8381613df9565b612fa25780604051630c89984b60e31b81526004016103169190615e3b565b50565b60605f612fb28484613e27565b9050808015612fd357505f3d1180612fd357505f846001600160a01b03163b115b15612fe857612fe0613e3a565b9150506102b4565b801561301257604051639996b31560e01b81526001600160a01b0385166004820152602401610316565b3d1561302557613020613e53565b61303e565b60405163d6bda27560e01b815260040160405180910390fd5b5092915050565b604080516080810182525f8082526020820181905291810182905260608101919091526130728383613e5e565b825260408201526130838284613e5e565b6020830152606082015292915050565b5f80516020615ff9833981519152546002036130c257604051633ee5aeb560e01b815260040160405180910390fd5b565b5f80851584151781871282861218178584141780156130e95786859250925050611da5565b505f858413156130fd575092949193919260015b8386035f8112604c8213178015613130578215613122575f8994509450505050611da5565b885f94509450505050611da5565b600a82900a8981028a82828161314857613148615e08565b0514613174578415613164575f8b965096505050505050611da5565b8a5f965096505050505050611da5565b8415613189578896509450611da59350505050565b9550879450611da59350505050565b5f805f6131a484613ec7565b909250905060018260038111156131bd576131bd615e4d565b141580156131dc57505f8260038111156131d9576131d9615e4d565b14155b156103bb57838260405163ee07877f60e01b8152600401610316929190615e61565b5f806001600160e01b038416601b0b60e085901d61321d828287613f54565b9350935050505b9250929050565b5f805f805f61323a87876140ba565b9250925092505f8061324c85856140fd565b915091508183801561325b5750815b9650965050505050509250929050565b60605f825167ffffffffffffffff81111561328857613288614e34565b6040519080825280602002602001820160405280156132b1578160200160208202803683370190505b5090505f808451116132c3575f6132c9565b83516001015b85516001010190505f8167ffffffffffffffff8111156132eb576132eb614e34565b60405190808252806020026020018201604052801561331e57816020015b60608152602001906001900390816133095790505b5090505f613342604080516002815233602082015230818301526060810190915290565b828281518110613354576133546156d8565b60200260200101819052505f5b87518110156133b1578180600101925050878181518110613384576133846156d8565b602002602001015183838151811061339e5761339e6156d8565b6020908102919091010152600101613361565b50855115613543578080600101915050838282815181106133d4576133d46156d8565b60200260200101819052505f5b8651811015613541576134908782815181106133ff576133ff6156d8565b60200260200101515f015161346d61343b8a8581518110613422576134226156d8565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b89848151811061347f5761347f6156d8565b6020026020010151604001516141d5565b6134b057604051630a57f30960e31b815260048101829052602401610316565b8681815181106134c2576134c26156d8565b60200260200101515f01516001600160a01b03165f1b8582815181106134ea576134ea6156d8565b6020026020010181815250508180600101925050868181518110613510576135106156d8565b60200260200101516020015183838151811061352e5761352e6156d8565b60209081029190910101526001016133e1565b505b5095945050505050565b5f805f6131a484614245565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f511483166135af5783831516156135a3573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b6040516323b872dd60e01b5f8181526001600160a01b038781166004528616602452604485905291602083606481808c5af1925060015f5114831661361757838315161561360b573d5f823e3d81fd5b5f883b113d1516831692505b604052505f60605295945050505050565b5f8085158415178015613640575f92505f915061373d565b61364a8487615e9a565b91505f613656886142a4565b90505f613662876142a4565b90505f61366f83836142d2565b5090505f6f0785ee10d5da46d900f436a0000000008211156136a4576f0785ee10d5da46d900f436a000000000820491506025015b670de0b6b3a76400008211156136c557670de0b6b3a7640000820491506012015b633b9aca008211156136de57633b9aca00820491506009015b6127108211156136f357612710820491506004015b811561370757600a820491506001016136f3565b6137118187615e9a565b95506137338b8a61372d878761372887600a615f99565b6142ee565b896143ba565b9097509550505050505b5094509492505050565b5f805f61375485856140fd565b9150915080158015613764575081155b1561378c57604051638eba4d0760e01b81526004810186905260248101859052604401610316565b509392505050565b5f806137a0848461445a565b90945092506137b186868686613cfb565b9150915094509492505050565b5f80835f036137ea57604051637a97930f60e01b81526004810187905260248101869052604401610316565b855f036137fb57505f905080611da5565b5f805f806138098a8a6144af565b919b509950915061381a88886144af565b919950975090505f61382b8b6142a4565b90505f6138378a6142a4565b90507f161bcca7119915b50764b4abe86529797775a5f1719510000000000000000000604c81831015613bfc57841561388e57507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b9050604b613bd4565b6f4b3b4ca85a86c47a098a2240000000008310156139ba57678ac7230489e8000083101561391e576402540be4008310156138ec57620186a08310156138dc5750620186a090506005613b95565b506402540be4009050600a613b95565b655af3107a400083101561390b5750655af3107a40009050600e613b95565b50678ac7230489e8000090506013613b95565b6b204fce5e3e250261100000008310156139705769152d02c7e14af6800000831015613959575069152d02c7e14af680000090506017613b95565b506b204fce5e3e250261100000009050601c613b95565b6d314dc6448d9338c15b0a0000000083101561399f57506d314dc6448d9338c15b0a0000000090506021613b95565b506f4b3b4ca85a86c47a098a22400000000090506026613b95565b780197d4df19d605767337e9f14d3eec8920e400000000000000831015613ab25773af298d050e4395d69670b12b7f41000000000000831015613a4d577172cb5bd86321e38cb6ce6682e80000000000831015613a2e57507172cb5bd86321e38cb6ce6682e800000000009050602b613b95565b5073af298d050e4395d69670b12b7f4100000000000090506030613b95565b76010b46c6cdd6e3e0828f4db456ff0c8ea0000000000000831015613a8e575076010b46c6cdd6e3e0828f4db456ff0c8ea000000000000090506035613b95565b50780197d4df19d605767337e9f14d3eec8920e4000000000000009050603a613b95565b7c03b58e88c75313ec9d329eaaa18fb92f75215b17100000000000000000831015613b48577a026e4d30eccc3215dd8f3157d27e23acbdcfe68000000000000000831015613b2057507a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000009050603f613b95565b507c03b58e88c75313ec9d329eaaa18fb92f75215b1710000000000000000090506044613b95565b7e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000831015613b9557507e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000905060495b818311613baa57600a820491505f1901613b95565b815f03613bd4576040516305e51ecb60e01b8152600481018d9052602481018c9052604401610316565b85613bfc576040516305e51ecb60e01b8152600481018f9052602481018e9052604401610316565b80600160ff1b018d12613c1357808d039c50613c51565b600160ff1b9c90038c015f811315613c5157806001600160ff1b03038b13613c3e57998a0199613c51565b5f80995099505050505050505050611da5565b5f808e128015613c6057505f8c135b15613c8157600160ff1b8e01808d13613c79575f613c7d565b808d035b9150505b8b818f01039750613c9e8f8e613c988887896142ee565b8b6143ba565b90995097505f811315613ce857604c811315613cc8575f809a509a50505050505050505050611da5565b80600a0a8981613cda57613cda615e08565b059850885f03613ce8575f97505b50969850949650611da595505050505050565b5f8085158415178015613d2757865f03613d1b5784849250925050611da5565b86869250925050611da5565b613d318787614709565b9097509550613d408585614709565b909550935085841315613d54579395929492935b838603604c811115613d6d578787935093505050611da5565b80600a0a8681613d7f57613d7f615e08565b0595505086850180881860ff90811c151589881890911c15168015613de857876001600160ff1b0303613dcf5760405163d556b11160e01b8152600481018a905260248101899052604401610316565b600a968790059690980586019760019790970196613dec565b8198505b5096979596505050505050565b5f600882511015613e0b57505f919050565b506008015167ffffffffffffffff1667ff0a89c674ee78741490565b5f805f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f80613e7b8460600151856040015161281e90919063ffffffff16565b915083604001519050613e9b836040015183611b4c90919063ffffffff16565b156132245782604001519150613ebe84606001518361289b90919063ffffffff16565b90509250929050565b5f80613ed1614752565b60405163b7bad1b160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb93899063b7bad1b19060240160408051808303815f875af1158015613f27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f4b9190615fa4565b91509150915091565b5f805f851215613f8157604051634a7d166b60e01b81526004810186905260248101859052604401610316565b845f03613f9357505f90506001611cb6565b8460ff8416850185811215613fc55760405163d556b11160e01b81526004810188905260248101879052604401610316565b5f805f83121561401157604c19831215613fe8575f809550955050505050611cb6565b825f03600a0a9150818481613fff57613fff615e08565b0495505084029091149150611cb69050565b5f8313156140aa57604d83131561404e5760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b82600a0a9150815f198161406457614064615e08565b048411156140985760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b5091909102925060019150611cb69050565b8360019550955050505050611cb6565b5f808060ff841681036001600160ff1b038611156140ec57600a860460018201600a88065f14935093509350506140f6565b8593509150600190505b9250925092565b5f601b83900b8314838382614161577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e100000000000000000086051561414157620186a0860595506005850194505b8586601b0b1461415c57600a86059550846001019450614141565b614177565b855f0361417757505f9250600191506132249050565b848560030b146141ba575f85121561419757505f92508291506132249050565b60405163d556b11160e01b81526004810183905260248101829052604401610316565b50506001600160e01b03841660e084901b1791509250929050565b5f836001600160a01b03163b5f03614233575f806141f385856147dd565b5090925090505f81600381111561420c5761420c615e4d565b14801561422a5750856001600160a01b0316826001600160a01b0316145b925050506103bb565b61423e848484614823565b90506103bb565b5f8061424f614752565b604051630782d7e160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb938990630782d7e1906024016040805180830381865afa158015613f27573d5f803e3d5ffd5b5f808212156142c957600160ff1b82036142c35750600160ff1b919050565b505f0390565b5090565b919050565b5f805f1983850993909202808410938190039390930393915050565b5f805f6142fb86866142d2565b91509150815f0361431f5783818161431557614315615e08565b04925050506103bb565b8382106143505760405163362ced0960e11b8152600481018790526024810186905260448101859052606401610316565b5f84868809600186198101871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103025f82900382900490920185841190960395909502919093039390930492909217029150509392505050565b5f805f8587181215614436576001600160ff1b03841115614423576143e76001600160ff1b03600161567f565b84036143fb5750600160ff1b905081611da5565b614406600a85615e1c565b61440f90615fe4565b61441a846001615e9a565b91509150611da5565b61442c84615fe4565b8391509150611da5565b6001600160ff1b038411156144505761440f600a85615e1c565b5082905081611da5565b5f80600160ff1b84036144a5576001600160ff1b0383036144985760405163d556b11160e01b81526004810185905260248101849052604401610316565b600a840593508260010192505b50505f9190910391565b5f805f845f036144c757505f915081905060016140f6565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85055f036146b4576f4b3b4ca85a86c47a098a224000000000850515801561452957507f80000000000000000000000000000000000000000000000000000000000000268412155b1561454a576f4b3b4ca85a86c47a098a224000000000850294506026840393505b7728c87cb5c89a2571ebfdcb54864ada834a00000000000000850515801561459257507f80000000000000000000000000000000000000000000000000000000000000138412155b156145ab57678ac7230489e80000850294506013840393505b7b097edd871cfda3a5697758bf0e3cbb5ac5741c64000000000000000085051580156145f757507f800000000000000000000000000000000000000000000000000000000000000a8412155b1561460d576402540be40085029450600a840393505b7e3899162693736ac531a5a58f1fbb4b746504382ca7e4000000000000000000850515801561465c57507f80000000000000000000000000000000000000000000000000000000000000028412155b156146725760648502945060028403935061460d565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85051580156146a257506001600160ff1b018412155b156146b457600a850294506001840393505b600a808602908105861480156146d157506001600160ff1b018512155b156146e0578095506001850394505b50939492935050507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b8305151590565b5f805f805f61471887876144af565b92509250925080614746576040516305e51ecb60e01b81526004810188905260248101879052604401610316565b50909590945092505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b15806147a9575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b156130c2576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610316565b5f805f8351604103614814576020840151604085015160608601515f1a61480688828585614874565b9550955095505050506140f6565b505081515f91506002906140f6565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156148ad57505f91506003905082614932565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156148fe573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661492957505f925060019150829050614932565b92505f91508190505b9450945094915050565b604051806080016040528061494f614968565b81526020015f81526020015f8152602001606081525090565b6040518060a001604052805f6001600160a01b031681526020016149b660405180606001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b8152606060208201819052604082018190525f91015290565b6040518060e001604052806149e2614968565b81526020015f81526020015f80191681526020015f8019168152602001606081526020015f8152602001606081525090565b5f60208284031215614a24575f80fd5b81356001600160e01b0319811681146103bb575f80fd5b5f8083601f840112614a4b575f80fd5b50813567ffffffffffffffff811115614a62575f80fd5b6020830191508360208260051b8501011115613224575f80fd5b5f805f60408486031215614a8e575f80fd5b833567ffffffffffffffff80821115614aa5575f80fd5b9085019060a08288031215614ab8575f80fd5b90935060208501359080821115614acd575f80fd5b50614ada86828701614a3b565b9497909650939450505050565b5f60208284031215614af7575f80fd5b5035919050565b6001600160a01b0381168114612fa2575f80fd5b80356142cd81614afe565b5f805f805f60808688031215614b31575f80fd5b8535614b3c81614afe565b94506020860135935060408601359250606086013567ffffffffffffffff811115614b65575f80fd5b614b7188828901614a3b565b969995985093965092949392505050565b5f805f60608486031215614b94575f80fd5b8335614b9f81614afe565b92506020840135614baf81614afe565b929592945050506040919091013590565b5f805f805f60808688031215614bd4575f80fd5b8535614bdf81614afe565b94506020860135614bef81614afe565b935060408601359250606086013567ffffffffffffffff80821115614c12575f80fd5b818801915088601f830112614c25575f80fd5b813581811115614c33575f80fd5b896020828501011115614c44575f80fd5b9699959850939650602001949392505050565b5f60208284031215614c67575f80fd5b81356103bb81614afe565b5f60c08284031215614c82575f80fd5b50919050565b5f60208284031215614c98575f80fd5b813567ffffffffffffffff811115614cae575f80fd5b61052d84828501614c72565b5f805f60408486031215614ccc575f80fd5b833567ffffffffffffffff80821115614ce3575f80fd5b614cef87838801614c72565b94506020860135915080821115614acd575f80fd5b5f60208284031215614d14575f80fd5b813567ffffffffffffffff811115614d2a575f80fd5b8201608081850312156103bb575f80fd5b5f8060208385031215614d4c575f80fd5b823567ffffffffffffffff811115614d62575f80fd5b614d6e85828601614a3b565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614dfd57603f19888603018452614deb858351614d7a565b94509285019290850190600101614dcf565b5092979650505050505050565b5f8060408385031215614e1b575f80fd5b8235614e2681614afe565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b60405290565b6040805190810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b60405160a0810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b604051601f8201601f1916810167ffffffffffffffff81118282101715614ee057614ee0614e34565b604052919050565b5f82601f830112614ef7575f80fd5b813567ffffffffffffffff811115614f1157614f11614e34565b614f24601f8201601f1916602001614eb7565b818152846020838601011115614f38575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608284031215614f64575f80fd5b614f6c614e48565b90508135614f7981614afe565b81526020820135614f8981614afe565b6020820152604082013567ffffffffffffffff811115614fa7575f80fd5b614fb384828501614ee8565b60408301525092915050565b5f67ffffffffffffffff821115614fd857614fd8614e34565b5060051b60200190565b5f60408284031215614ff2575f80fd5b614ffa614e71565b9050813561500781614afe565b808252506020820135602082015292915050565b5f82601f83011261502a575f80fd5b8135602061503f61503a83614fbf565b614eb7565b8083825260208201915060208460061b870101935086841115615060575f80fd5b602086015b84811015615085576150778882614fe2565b835291830191604001615065565b509695505050505050565b5f60a082840312156150a0575f80fd5b6150a8614e94565b90506150b382614b12565b8152602082013567ffffffffffffffff808211156150cf575f80fd5b6150db85838601614f54565b602084015260408401359150808211156150f3575f80fd5b6150ff8583860161501b565b60408401526060840135915080821115615117575f80fd5b506151248482850161501b565b6060830152506080820135608082015292915050565b5f61514761503a84614fbf565b8381529050602080820190600585811b850187811115615165575f80fd5b855b8181101561525257803567ffffffffffffffff80821115615186575f80fd5b908801906060828c031215615199575f80fd5b6151a1614e48565b82356151ac81614afe565b815282870135828111156151be575f80fd5b8301601f81018d136151ce575f80fd5b80356151dc61503a82614fbf565b81815290881b8201890190898101908f8311156151f7575f80fd5b928a01925b828410156152155783358252928a0192908a01906151fc565b848b0152506040915050838101358381111561522f575f80fd5b61523b8e828701614ee8565b918301919091525087525050938301938301615167565b50505050509392505050565b5f82601f83011261526d575f80fd5b6103bb8383356020850161513a565b5f805f805f6101408688031215615291575f80fd5b853567ffffffffffffffff808211156152a8575f80fd5b6152b489838a01615090565b965060208801359150808211156152c9575f80fd5b6152d589838a01615090565b95506152e48960408a01614c72565b94506101008801359150808211156152fa575f80fd5b61530689838a0161525e565b935061012088013591508082111561531c575f80fd5b506153298882890161525e565b9150509295509295909350565b5f6102b43683615090565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f813561537581614afe565b6001600160a01b03908116845260208301359061539182614afe565b166020840152604082013536839003601e190181126153ae575f80fd5b820160208101903567ffffffffffffffff8111156153ca575f80fd5b8036038213156153d8575f80fd5b606060408601526153ed606086018284615341565b95945050505050565b5f808335601e1984360301811261540b575f80fd5b830160208101925035905067ffffffffffffffff81111561542a575f80fd5b8060061b3603821315613224575f80fd5b8183525f60208085019450825f5b8581101561548157813561545c81614afe565b6001600160a01b03168752818301358388015260409687019690910190600101615449565b509495945050505050565b5f6001600160a01b0380861683528460208401526060604084015283356154b281614afe565b166060830152602083013536849003605e190181126154cf575f80fd5b60a060808401526154e66101008401858301615369565b90506154f560408501856153f6565b605f19808685030160a087015261550d84838561543b565b935061551c60608801886153f6565b93509150808685030160c08701525061553683838361543b565b92505050608084013560e084015280915050949350505050565b5f61555d61503a84614fbf565b80848252602080830192508560051b85013681111561557a575f80fd5b855b8181101561560457803567ffffffffffffffff8082111561559b575f80fd5b8189019150604082360312156155af575f80fd5b6155b7614e71565b8235828111156155c5575f80fd5b6155d136828601614f54565b82525085830135828111156155e4575f80fd5b6155f03682860161525e565b82880152508752505093820193820161557c565b50919695505050505050565b5f6001600160a01b03808916835280881660208401525085604083015284606083015260a0608083015261564860a083018486615341565b98975050505050505050565b5f60208284031215615664575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102b4576102b461566b565b5f808335601e198436030181126156a7575f80fd5b83018035915067ffffffffffffffff8211156156c1575f80fd5b6020019150600581901b3603821315613224575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112615700575f80fd5b9190910192915050565b5f8235609e19833603018112615700575f80fd5b5f808335601e19843603018112615733575f80fd5b83018035915067ffffffffffffffff82111561574d575f80fd5b6020019150600681901b3603821315613224575f80fd5b5f60808236031215615774575f80fd5b6040516080810167ffffffffffffffff828210818311171561579857615798614e34565b8160405284359150808211156157ac575f80fd5b6157b836838701615090565b8352602085013560208401526040850135604084015260608501359150808211156157e1575f80fd5b506157ee3682860161525e565b60608301525092915050565b5f6020828403121561580a575f80fd5b813580151581146103bb575f80fd5b5f815180845260208085019450602084015f5b8381101561548157815180516001600160a01b03168852830151838801526040909601959082019060010161582c565b5f6001600160a01b03808351168452602083015160a060208601528181511660a08601528160208201511660c08601526040810151915050606060e08501526158a9610100850182614d7a565b9050604083015184820360408601526158c28282615819565b915050606083015184820360608601526158dc8282615819565b915050608083015160808501528091505092915050565b5f815180845260208085019450602084015f5b8381101561548157815187529582019590820190600101615906565b5f6001600160a01b0380871683526020608081850152865160808086015261594e61010086018261585c565b90508188015160a086015260408089015160c08701526060808a0151607f198885030160e08901528381518086528686019150868160051b87010187840193505f5b828110156159ea57601f1988830301845284518a815116835289810151878b8501526159be888501826158f3565b91890151848303858b01529190506159d68183614d7a565b968b0196958b019593505050600101615990565b5080995050505050505050505083604083015282606083015295945050505050565b5f808335601e19843603018112615a21575f80fd5b83018035915067ffffffffffffffff821115615a3b575f80fd5b602001915036819003821315613224575f80fd5b5f8235605e19833603018112615700575f80fd5b5f6102b43683614f54565b5f60408284031215615a7e575f80fd5b6103bb8383614fe2565b6001600160a01b0384168152826020820152606060408201525f6153ed606083018461585c565b6001600160a01b0385168152836020820152606060408201525f615ad7606083018486615341565b9695505050505050565b5f6103bb36848461513a565b818103818111156102b4576102b461566b565b828482375f8382015f815283518060208601835e5f910190815295945050505050565b5f6101206001600160a01b0387168352806020840152615b458184018761585c565b90508281036040840152615b59818661585c565b9150508235606083015260208301356080830152604083013560a0830152606083013560c0830152608083013560e083015260a083013561010083015295945050505050565b602081525f6103bb602083018461585c565b5f60018201615bc257615bc261566b565b5060010190565b5f8282518085526020808601955060208260051b840101602086015f5b84811015615c1457601f19868403018952615c028383516158f3565b98840198925090830190600101615be6565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e06060840152615c5a610100840182614d7a565b9050606084015160808401526080840151601f19808584030160a0860152615c828383615bc9565b925060a08601519150808584030160c0860152615c9f83836158f3565b925060c08601519150808584030160e0860152506153ed82826158f3565b5f82601f830112615ccc575f80fd5b81516020615cdc61503a83614fbf565b8083825260208201915060208460051b870101935086841115615cfd575f80fd5b602086015b848110156150855780518352918301918301615d02565b5f8060408385031215615d2a575f80fd5b825167ffffffffffffffff80821115615d41575f80fd5b818501915085601f830112615d54575f80fd5b81516020615d6461503a83614fbf565b82815260059290921b84018101918181019089841115615d82575f80fd5b948201945b83861015615da057855182529482019490820190615d87565b91880151919650909350505080821115615db8575f80fd5b50615dc585828601615cbd565b9150509250929050565b828152604060208201525f61052d60408301846158f3565b6001600160a01b0383168152604060208201525f61052d6040830184615bc9565b634e487b7160e01b5f52601260045260245ffd5b5f82615e3657634e487b7160e01b5f52601260045260245ffd5b500490565b602081525f6103bb6020830184614d7a565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040810160048310615e8d57634e487b7160e01b5f52602160045260245ffd5b8260208301529392505050565b8082018281125f8312801582168215821617156114ac576114ac61566b565b600181815b80851115615ef357815f1904821115615ed957615ed961566b565b80851615615ee657918102915b93841c9390800290615ebe565b509250929050565b5f82615f09575060016102b4565b81615f1557505f6102b4565b8160018114615f2b5760028114615f3557615f51565b60019150506102b4565b60ff841115615f4657615f4661566b565b50506001821b6102b4565b5060208310610133831016604e8410600b8410161715615f74575081810a6102b4565b615f7e8383615eb9565b805f1904821115615f9157615f9161566b565b029392505050565b5f6103bb8383615efb565b5f8060408385031215615fb5575f80fd5b825160048110615fc3575f80fd5b602084015190925060ff81168114615fd9575f80fd5b809150509250929050565b5f600160ff1b82016142c3576142c361566b56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00", "linkReferences": {} } } diff --git a/src/concrete/raindex/RaindexV6.sol b/src/concrete/raindex/RaindexV6.sol index e2af849d7a..09733ec655 100644 --- a/src/concrete/raindex/RaindexV6.sol +++ b/src/concrete/raindex/RaindexV6.sol @@ -213,6 +213,20 @@ contract RaindexV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Raindex mapping(address owner => mapping(address token => mapping(bytes32 vaultId => Float balance))) internal sVaultBalances; + /// @dev Per `(user, token)` ledger of the sub-base-unit remainder that the + /// orderbook holds on behalf of `user` but has not yet moved, because a + /// lossy float->fixed-decimal conversion in `pullTokens`/`pushTokens` cannot + /// transfer a fraction of a base unit. The credit is always non-negative and + /// strictly less than one base unit: whenever it reaches a whole base unit it + /// is realized into the next token move for that `(user, token)`. It is + /// denominated in token units (a `Float`) so it is independent of the token's + /// decimals. Every credit is backed by real tokens the orderbook already + /// holds (a pull rounds the transfer up, a push rounds it down), so realizing + /// it only ever releases provable excess and never dips into a vault balance. + // Solhint and slither disagree on this. Slither wins. + //solhint-disable-next-line private-vars-leading-underscore + mapping(address user => mapping(address token => Float credit)) internal sDustCredit; + /// @inheritdoc IRaindexV6 function vaultBalance2(address owner, address token, bytes32 vaultId) external view override returns (Float) { return _vaultBalance(owner, token, vaultId); @@ -1160,26 +1174,73 @@ contract RaindexV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Raindex /// never pulls in less than the vault accounting credits. `pushTokens` rounds /// DOWN for the same protocol-favoring reason. Together this keeps the /// orderbook solvent — its real token balance is always >= the sum of the - /// vault balances — but each lossy conversion leaves a sub-token-unit residue - /// in the contract that is not attributed to any vault and has no recovery - /// path. Such dust is under one base unit per conversion and can never cause - /// insolvency. + /// vault balances. The sub-base-unit residue each lossy conversion would + /// otherwise strand is instead booked into `sDustCredit[account][token]` and + /// realized into the next move for the same `(account, token)`: the pull is + /// reduced by any whole base unit of standing credit, and the fresh over-pull + /// is added to it. The credit is always backed by tokens the orderbook holds + /// for `account`, so this is exactly conservative and never insolvent. Near + /// the Float coefficient ceiling, where the credit subtraction and conversion + /// can truncate the pull below the requested base units, the pull is clamped + /// up to the full requested amount so solvency still holds. function pullTokens(address account, address token, Float amount) internal returns (uint256, uint8) { uint8 decimals = _safeDecimals(token); if (amount.lt(LibDecimalFloat.FLOAT_ZERO)) { revert NegativePull(); } - (uint256 amount18, bool lossless) = LibDecimalFloat.toFixedDecimalLossy(amount, decimals); - // Round truncation up when pulling. - if (!lossless) { - // This needs to be checked math as an overflow would cause tokens - // to silently not be pulled (wraps to 0). - ++amount18; - } - if (amount18 > 0) { + // The orderbook already holds the standing credit (token units) for + // `account` from prior over-pulls / under-pushes, so it only needs to + // pull in the part of `amount` that the credit does not already cover. + Float credit = sDustCredit[account][token]; + Float effective = amount.sub(credit); + + uint256 amount18 = 0; + bool clamped = false; + // A non-positive `effective` means the credit already covers the whole + // pull, so no tokens move; `toFixedDecimalLossy` also rejects negatives. + if (effective.gt(LibDecimalFloat.FLOAT_ZERO)) { + bool lossless; + (amount18, lossless) = LibDecimalFloat.toFixedDecimalLossy(effective, decimals); + // Round truncation up when pulling. + if (!lossless) { + // This needs to be checked math as an overflow would cause tokens + // to silently not be pulled (wraps to 0). + ++amount18; + } + + // Near the Float coefficient ceiling the `amount.sub(credit)` above + // can drop the sub-unit credit AND `toFixedDecimalLossy` can report a + // spuriously-lossless conversion that truncates `effective` DOWN by + // more than one base unit, so the round-up never fires and the pull + // falls short of the vault obligation it books. `obligation` is the + // full requested `amount` in base units (what a zero-credit pull would + // take); the standing credit can only ever reduce the pull by under one + // base unit, so when the rounded `amount18` lands two or more base units + // below `obligation` the credit was dropped. Clamp up to `obligation` + // so the orderbook is never short; the credit is then carried forward + // below rather than re-derived from the unreliable `effective`. + //slither-disable-next-line unused-return + (uint256 obligation,) = LibDecimalFloat.toFixedDecimalLossy(amount, decimals); + if (amount18 + 1 < obligation) { + amount18 = obligation; + clamped = true; + } + IERC20(token).safeTransferFrom(account, address(this), amount18); } + + // The new credit is the transferred amount minus what `effective` + // required: the over-pull when tokens moved (rounded up, so non-negative + // and under one base unit), or the leftover credit when none did. It is + // backed by tokens the orderbook holds for `account`. A clamped pull moved + // exactly `amount` in base units (the standing credit was sub-resolution + // beside it and could not reduce the pull), so the standing credit carries + // forward unchanged. + //slither-disable-next-line unused-return + (Float pulled,) = LibDecimalFloat.fromFixedDecimalLossyPacked(amount18, decimals); + sDustCredit[account][token] = clamped ? credit : pulled.sub(effective); + return (amount18, decimals); } @@ -1188,8 +1249,11 @@ contract RaindexV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Raindex /// /// A lossy float->fixed-decimal conversion is truncated (rounded DOWN) here /// so the contract never sends more than the vault accounting debits. See - /// `pullTokens` for the full rounding policy and its solvency / residual-dust - /// tradeoff. + /// `pullTokens` for the full rounding policy. The sub-base-unit residue each + /// lossy conversion would otherwise strand is booked into + /// `sDustCredit[account][token]` and realized into the next move for the same + /// `(account, token)`: the push is increased by any whole base unit of + /// standing credit, and the fresh under-push is added to it. function pushTokens(address account, address token, Float amountFloat) internal returns (uint256, uint8) { uint8 decimals = _safeDecimals(token); @@ -1197,8 +1261,19 @@ contract RaindexV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Raindex revert NegativePush(); } + // The orderbook also owes `account` the standing credit from prior + // under-pushes, so the total it may send is `amountFloat + credit`. + Float effective = amountFloat.add(sDustCredit[account][token]); + + //slither-disable-next-line unused-return + (uint256 amount,) = LibDecimalFloat.toFixedDecimalLossy(effective, decimals); + // The shortfall truncated away is the new credit. It is non-negative + // because the transfer was rounded down, and under one base unit because + // truncation drops less than one base unit. //slither-disable-next-line unused-return - (uint256 amount,) = LibDecimalFloat.toFixedDecimalLossy(amountFloat, decimals); + (Float pushed,) = LibDecimalFloat.fromFixedDecimalLossyPacked(amount, decimals); + sDustCredit[account][token] = effective.sub(pushed); + if (amount > 0) { IERC20(token).safeTransfer(account, amount); } diff --git a/src/generated/GenericPoolRaindexV6ArbOrderTaker.pointers.sol b/src/generated/GenericPoolRaindexV6ArbOrderTaker.pointers.sol index 2fee2ffc2d..8874a508d1 100644 --- a/src/generated/GenericPoolRaindexV6ArbOrderTaker.pointers.sol +++ b/src/generated/GenericPoolRaindexV6ArbOrderTaker.pointers.sol @@ -10,12 +10,12 @@ pragma solidity ^0.8.25; // file needs the contract to exist so that it can be compiled. /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0xc4492cb22d918a3f0d41f13e533744ef03a2e7f744ec0a43b79d97a04c537544); +bytes32 constant BYTECODE_HASH = bytes32(0xd3453fd739378f1ccce8181a1ba3554db33e3fc13f6eeda83d2abc716c45d89b); /// @dev The deterministic deploy address of the contract when deployed via /// the Zoltu factory. -address constant DEPLOYED_ADDRESS = address(0xc0c17e58018C80A5420dF7756acd2B2dcf37e380); +address constant DEPLOYED_ADDRESS = address(0xe2a825c9C2b52F7c73f30080680DdB90f36ed9c3); /// @dev The runtime bytecode of the contract. bytes constant RUNTIME_CODE = - hex"608060405260043610610034575f3560e01c806301ffc9a71461003d578063691f9ed714610070578063b17c83c11461008f57005b3661003b57005b005b348015610048575f80fd5b5061005c610057366004611363565b6100a2565b604051901515815260200160405180910390f35b34801561007b575f80fd5b5061003b61008a36600461139e565b6100f3565b61003b61009d366004611440565b61013a565b5f6001600160e01b0319821663691f9ed760e01b14806100d257506001600160e01b0319821663b17c83c160e01b145b806100ed57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6101328683838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506103fc92505050565b505050505050565b6101426104ad565b61015161014e8261172f565b50565b61015e60808301836117eb565b90505f0361017f57604051639c95219f60e01b815260040160405180910390fd5b6001600160a01b0383167386594ac4319230870c6e587f4aca48fab575619e146101cc5760405163516e822d60e01b81526001600160a01b03841660048201526024015b60405180910390fd5b5f6101da60808401846117eb565b5f8181106101ea576101ea611831565b90506020028101906101fc9190611845565b6102069080611863565b610214906040810190611877565b61022160808601866117eb565b5f81811061023157610231611831565b90506020028101906102439190611845565b6020013581811061025657610256611831565b61026c92602060409092020190810191506118bd565b90505f61027c60808501856117eb565b5f81811061028c5761028c611831565b905060200281019061029e9190611845565b6102a89080611863565b6102b6906060810190611877565b6102c360808701876117eb565b5f8181106102d3576102d3611831565b90506020028101906102e59190611845565b604001358181106102f8576102f8611831565b61030e92602060409092020190810191506118bd565b90506103256001600160a01b038316865f196104db565b6040516334e3942b60e11b81526001600160a01b038616906369c7285690610351908790600401611b21565b60408051808303815f875af115801561036c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103909190611d21565b506103a790506001600160a01b038316865f6104db565b6103cc6103b38461172f565b836103bd85610555565b846103c786610555565b6105d9565b50506103f760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050565b5f805f838060200190518101906104139190611d43565b919450925090506001600160a01b038316610441576040516398521dc560e01b815260040160405180910390fd5b6001600160a01b0382166104685760405163456ac4c360e11b815260040160405180910390fd5b61047d6001600160a01b038616845f196104db565b6104916001600160a01b0383168247610878565b506104a66001600160a01b038616845f6104db565b5050505050565b6104b5610945565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6104e78383835f610989565b6103f7576104f883835f6001610989565b61052057604051635274afe760e01b81526001600160a01b03841660048201526024016101c3565b61052d8383836001610989565b6103f757604051635274afe760e01b81526001600160a01b03841660048201526024016101c3565b5f61055e6109eb565b6040516354636d2b60e01b81526001600160a01b038316600482015273200e12d10bb0c5e4a17e7018f0f1161919bb9389906354636d2b906024016020604051808303815f875af11580156105b5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100ed9190611dde565b6040805160018082528183019092525f91816020015b60608152602001906001900390816105ef575050604080516003808252608082019092529192505f919060208201606080368337019050506040516370a0823160e01b81523060048201529091505f906001600160a01b038816906370a0823190602401602060405180830381865afa15801561066e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106929190611dfe565b905080156106ae576106ae6001600160a01b0388163383610a76565b5f6106b98288610a83565b50905080835f815181106106cf576106cf611831565b602090810291909101015250506040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610720573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107449190611dfe565b90508015610760576107606001600160a01b0386163383610a76565b5f61076b8286610a83565b509050808360018151811061078257610782611831565b60209081029190910101525047905080156107a1576107a13382610ac4565b5f6107ad826012610a83565b50905080836002815181106107c4576107c4611831565b602002602001018181525050505080825f815181106107e5576107e5611831565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160a0810182525f918101828152606080830193909352608082018390528152602081019190915281526020019060019003908161080657905050905087815f8151811061085957610859611831565b602002602001018190525061086e8382610b22565b5050505050505050565b6060814710156108a45760405163cf47918160e01b8152476004820152602481018390526044016101c3565b5f6108b0858486610ce6565b90508080156108d157505f3d11806108d157505f856001600160a01b03163b115b156108e6576108de610cfb565b91505061093e565b801561091057604051639996b31560e01b81526001600160a01b03861660048201526024016101c3565b3d156109235761091e610d14565b61093c565b60405163d6bda27560e01b815260040160405180910390fd5b505b9392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005460020361098757604051633ee5aeb560e01b815260040160405180910390fd5b565b60405163095ea7b360e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f511483166109df5783831516156109d3573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b1580610a42575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b15610987576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb938960048201526024016101c3565b61052d8383836001610d1f565b5f805f805f610a928787610d69565b9250925092505f80610aa48585610dc5565b9150915081838015610ab35750815b9650965050505050505b9250929050565b80471015610aee5760405163cf47918160e01b8152476004820152602481018290526044016101c3565b610b07828260405180602001604052805f815250610ce6565b15610b10575050565b3d1561092357610b1e610d14565b5050565b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b865181101561086e57868181518110610b8957610b89611831565b602002602001015193505f845f015160400151511115610cde575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001610c018d8a60200151610eb2565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401610c2c9190611eca565b5f60405180830381865afa158015610c46573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610c6d9190810190611fcb565b9150505f81511115610cdc5784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490610cae908a908590600401612081565b5f604051808303815f87803b158015610cc5575f80fd5b505af1158015610cd7573d5f803e3d5ffd5b505050505b505b600101610b6e565b5f805f83516020850186885af1949350505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f511483166109df5783831516156109d3573d5f823e3d81fd5b5f808060ff841681037f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff861115610db457600a860460018201600a88065f1493509350935050610dbe565b8593509150600190505b9250925092565b5f601b83900b8314838382610e29577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e1000000000000000000860515610e0957620186a0860595506005850194505b8586601b0b14610e2457600a86059550846001019450610e09565b610e3f565b855f03610e3f57505f925060019150610abd9050565b848560030b14610e82575f851215610e5f57505f9250829150610abd9050565b60405163d556b11160e01b815260048101839052602481018290526044016101c3565b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841660e084901b1791509250929050565b60605f825167ffffffffffffffff811115610ecf57610ecf6114be565b604051908082528060200260200182016040528015610ef8578160200160208202803683370190505b5090505f80845111610f0a575f610f10565b83516001015b85516001010190505f8167ffffffffffffffff811115610f3257610f326114be565b604051908082528060200260200182016040528015610f6557816020015b6060815260200190600190039081610f505790505b5090505f610f89604080516002815233602082015230818301526060810190915290565b828281518110610f9b57610f9b611831565b60200260200101819052505f5b8751811015610ff8578180600101925050878181518110610fcb57610fcb611831565b6020026020010151838381518110610fe557610fe5611831565b6020908102919091010152600101610fa8565b5085511561118a5780806001019150508382828151811061101b5761101b611831565b60200260200101819052505f5b8651811015611188576110d787828151811061104657611046611831565b60200260200101515f01516110b46110828a858151811061106957611069611831565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b8984815181106110c6576110c6611831565b602002602001015160400151611194565b6110f757604051630a57f30960e31b8152600481018290526024016101c3565b86818151811061110957611109611831565b60200260200101515f01516001600160a01b03165f1b85828151811061113157611131611831565b602002602001018181525050818060010192505086818151811061115757611157611831565b60200260200101516020015183838151811061117557611175611831565b6020908102919091010152600101611028565b505b5095945050505050565b5f836001600160a01b03163b5f036111f2575f806111b28585611204565b5090925090505f8160038111156111cb576111cb6120a1565b1480156111e95750856001600160a01b0316826001600160a01b0316145b9250505061093e565b6111fd84848461124a565b905061093e565b5f805f835160410361123b576020840151604085015160608601515f1a61122d8882858561129b565b955095509550505050610dbe565b505081515f9150600290610dbe565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156112d457505f91506003905082611359565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611325573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661135057505f925060019150829050611359565b92505f91508190505b9450945094915050565b5f60208284031215611373575f80fd5b81356001600160e01b03198116811461093e575f80fd5b6001600160a01b038116811461014e575f80fd5b5f805f805f8060a087890312156113b3575f80fd5b86356113be8161138a565b955060208701356113ce8161138a565b94506040870135935060608701359250608087013567ffffffffffffffff808211156113f8575f80fd5b818901915089601f83011261140b575f80fd5b813581811115611419575f80fd5b8a602082850101111561142a575f80fd5b6020830194508093505050509295509295509295565b5f805f60608486031215611452575f80fd5b833561145d8161138a565b9250602084013567ffffffffffffffff80821115611479575f80fd5b9085019060c0828803121561148c575f80fd5b909250604085013590808211156114a1575f80fd5b508401604081870312156114b3575f80fd5b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156114f5576114f56114be565b60405290565b6040805190810167ffffffffffffffff811182821017156114f5576114f56114be565b604051601f8201601f1916810167ffffffffffffffff81118282101715611547576115476114be565b604052919050565b5f67ffffffffffffffff821115611568576115686114be565b50601f01601f191660200190565b5f82601f830112611585575f80fd5b81356115986115938261154f565b61151e565b8181528460208386010111156115ac575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff8211156115e1576115e16114be565b5060051b60200190565b5f82601f8301126115fa575f80fd5b8135602061160a611593836115c8565b82815260059290921b84018101918181019086841115611628575f80fd5b8286015b8481101561172457803567ffffffffffffffff8082111561164b575f80fd5b908801906060828b03601f19011215611662575f80fd5b61166a6114d2565b868301356116778161138a565b81526040838101358381111561168b575f80fd5b8401603f81018d1361169b575f80fd5b888101356116ab611593826115c8565b81815260059190911b82018301908a8101908f8311156116c9575f80fd5b928401925b828410156116e75783358252928b0192908b01906116ce565b858c01525050506060840135838111156116ff575f80fd5b61170d8d8a83880101611576565b91830191909152508552505091830191830161162c565b509695505050505050565b5f6040823603121561173f575f80fd5b6117476114fb565b823567ffffffffffffffff8082111561175e575f80fd5b818501915060608236031215611772575f80fd5b61177a6114d2565b82356117858161138a565b815260208301356117958161138a565b60208201526040830135828111156117ab575f80fd5b6117b736828601611576565b604083015250835260208501359150808211156117d2575f80fd5b506117df368286016115eb565b60208301525092915050565b5f808335601e19843603018112611800575f80fd5b83018035915067ffffffffffffffff82111561181a575f80fd5b6020019150600581901b3603821315610abd575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112611859575f80fd5b9190910192915050565b5f8235609e19833603018112611859575f80fd5b5f808335601e1984360301811261188c575f80fd5b83018035915067ffffffffffffffff8211156118a6575f80fd5b6020019150600681901b3603821315610abd575f80fd5b5f602082840312156118cd575f80fd5b813561093e8161138a565b5f808335601e198436030181126118ed575f80fd5b830160208101925035905067ffffffffffffffff81111561190c575f80fd5b8060051b3603821315610abd575f80fd5b5f8235605e19833603018112611931575f80fd5b90910192915050565b5f808335601e1984360301811261194f575f80fd5b830160208101925035905067ffffffffffffffff81111561196e575f80fd5b803603821315610abd575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f808335601e198436030181126119b9575f80fd5b830160208101925035905067ffffffffffffffff8111156119d8575f80fd5b8060061b3603821315610abd575f80fd5b8183525f60208085019450825f5b85811015611a2f578135611a0a8161138a565b6001600160a01b031687528183013583880152604096870196909101906001016119f7565b509495945050505050565b8183526020808401935f91600585811b8301820185855b88811015611b1357858303601f19018a52611a6c828961191d565b60608135611a798161138a565b6001600160a01b03168552611a90828801836118d8565b82898801528083880152608092507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115611aca575f80fd5b871b808288850137860190506040611ae48482018561193a565b9450838884030182890152611afc848401868361197c565b9e8a019e9750505093870193505050600101611a51565b509098975050505050505050565b5f602080835260e08301843582850152604082860135818601526060818701358187015280870135801515808214611b57575f80fd5b8060808901525050611b6c60808801886118d8565b60c060a08901529384905261010093848801600582901b89018601835f5b84811015611ce8578b830360ff19018452813536879003607e19018112611baf575f80fd5b8601803536829003609e19018112611bc5575f80fd5b6080855281018035611bd68161138a565b6001600160a01b038082166080880152611bf28e84018461191d565b915060a0808801528135611c058161138a565b8116610120880152818e0135611c1a8161138a565b16610140870152611c2d818c018261193a565b91508a610160880152611c456101808801838361197c565b915050611c548b8301836119a4565b607f19808985030160c08a0152611c6c8483856119e9565b9350611c7a8d8601866119a4565b93509150808985030160e08a015250611c948383836119e9565b9250505060808201358c8701528c8301358d8701528a8301358b870152611cbd8a8401846118d8565b935091508581038a870152611cd3818484611a3a565b968d019695505050918a019150600101611b8a565b5050611cf760a08c018c61193a565b8b8303601f190160c08d015298509650611d1281898961197c565b9b9a5050505050505050505050565b5f8060408385031215611d32575f80fd5b505080516020909101519092909150565b5f805f60608486031215611d55575f80fd5b8351611d608161138a565b6020850151909350611d718161138a565b604085015190925067ffffffffffffffff811115611d8d575f80fd5b8401601f81018613611d9d575f80fd5b8051611dab6115938261154f565b818152876020838501011115611dbf575f80fd5b8160208401602083015e5f602083830101528093505050509250925092565b5f60208284031215611dee575f80fd5b815160ff8116811461093e575f80fd5b5f60208284031215611e0e575f80fd5b5051919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f815180845260208085019450602084015f5b83811015611a2f57815187529582019590820190600101611e56565b5f8282518085526020808601955060208260051b840101602086015f5b84811015611ebd57601f19868403018952611eab838351611e43565b98840198925090830190600101611e8f565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e06060840152611f03610100840182611e15565b9050606084015160808401526080840151601f19808584030160a0860152611f2b8383611e72565b925060a08601519150808584030160c0860152611f488383611e43565b925060c08601519150808584030160e086015250611f668282611e43565b95945050505050565b5f82601f830112611f7e575f80fd5b81516020611f8e611593836115c8565b8083825260208201915060208460051b870101935086841115611faf575f80fd5b602086015b848110156117245780518352918301918301611fb4565b5f8060408385031215611fdc575f80fd5b825167ffffffffffffffff80821115611ff3575f80fd5b818501915085601f830112612006575f80fd5b81516020612016611593836115c8565b82815260059290921b84018101918181019089841115612034575f80fd5b948201945b8386101561205257855182529482019490820190612039565b9188015191965090935050508082111561206a575f80fd5b5061207785828601611f6f565b9150509250929050565b828152604060208201525f6120996040830184611e43565b949350505050565b634e487b7160e01b5f52602160045260245ffd"; + hex"608060405260043610610034575f3560e01c806301ffc9a71461003d578063691f9ed714610070578063b17c83c11461008f57005b3661003b57005b005b348015610048575f80fd5b5061005c610057366004611363565b6100a2565b604051901515815260200160405180910390f35b34801561007b575f80fd5b5061003b61008a36600461139e565b6100f3565b61003b61009d366004611440565b61013a565b5f6001600160e01b0319821663691f9ed760e01b14806100d257506001600160e01b0319821663b17c83c160e01b145b806100ed57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6101328683838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506103fc92505050565b505050505050565b6101426104ad565b61015161014e8261172f565b50565b61015e60808301836117eb565b90505f0361017f57604051639c95219f60e01b815260040160405180910390fd5b6001600160a01b0383167366f51a9c29480491c9282d99cf324e9f419a4e1d146101cc5760405163516e822d60e01b81526001600160a01b03841660048201526024015b60405180910390fd5b5f6101da60808401846117eb565b5f8181106101ea576101ea611831565b90506020028101906101fc9190611845565b6102069080611863565b610214906040810190611877565b61022160808601866117eb565b5f81811061023157610231611831565b90506020028101906102439190611845565b6020013581811061025657610256611831565b61026c92602060409092020190810191506118bd565b90505f61027c60808501856117eb565b5f81811061028c5761028c611831565b905060200281019061029e9190611845565b6102a89080611863565b6102b6906060810190611877565b6102c360808701876117eb565b5f8181106102d3576102d3611831565b90506020028101906102e59190611845565b604001358181106102f8576102f8611831565b61030e92602060409092020190810191506118bd565b90506103256001600160a01b038316865f196104db565b6040516334e3942b60e11b81526001600160a01b038616906369c7285690610351908790600401611b21565b60408051808303815f875af115801561036c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103909190611d21565b506103a790506001600160a01b038316865f6104db565b6103cc6103b38461172f565b836103bd85610555565b846103c786610555565b6105d9565b50506103f760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050565b5f805f838060200190518101906104139190611d43565b919450925090506001600160a01b038316610441576040516398521dc560e01b815260040160405180910390fd5b6001600160a01b0382166104685760405163456ac4c360e11b815260040160405180910390fd5b61047d6001600160a01b038616845f196104db565b6104916001600160a01b0383168247610878565b506104a66001600160a01b038616845f6104db565b5050505050565b6104b5610945565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6104e78383835f610989565b6103f7576104f883835f6001610989565b61052057604051635274afe760e01b81526001600160a01b03841660048201526024016101c3565b61052d8383836001610989565b6103f757604051635274afe760e01b81526001600160a01b03841660048201526024016101c3565b5f61055e6109eb565b6040516354636d2b60e01b81526001600160a01b038316600482015273200e12d10bb0c5e4a17e7018f0f1161919bb9389906354636d2b906024016020604051808303815f875af11580156105b5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100ed9190611dde565b6040805160018082528183019092525f91816020015b60608152602001906001900390816105ef575050604080516003808252608082019092529192505f919060208201606080368337019050506040516370a0823160e01b81523060048201529091505f906001600160a01b038816906370a0823190602401602060405180830381865afa15801561066e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106929190611dfe565b905080156106ae576106ae6001600160a01b0388163383610a76565b5f6106b98288610a83565b50905080835f815181106106cf576106cf611831565b602090810291909101015250506040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610720573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107449190611dfe565b90508015610760576107606001600160a01b0386163383610a76565b5f61076b8286610a83565b509050808360018151811061078257610782611831565b60209081029190910101525047905080156107a1576107a13382610ac4565b5f6107ad826012610a83565b50905080836002815181106107c4576107c4611831565b602002602001018181525050505080825f815181106107e5576107e5611831565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160a0810182525f918101828152606080830193909352608082018390528152602081019190915281526020019060019003908161080657905050905087815f8151811061085957610859611831565b602002602001018190525061086e8382610b22565b5050505050505050565b6060814710156108a45760405163cf47918160e01b8152476004820152602481018390526044016101c3565b5f6108b0858486610ce6565b90508080156108d157505f3d11806108d157505f856001600160a01b03163b115b156108e6576108de610cfb565b91505061093e565b801561091057604051639996b31560e01b81526001600160a01b03861660048201526024016101c3565b3d156109235761091e610d14565b61093c565b60405163d6bda27560e01b815260040160405180910390fd5b505b9392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005460020361098757604051633ee5aeb560e01b815260040160405180910390fd5b565b60405163095ea7b360e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f511483166109df5783831516156109d3573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b1580610a42575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b15610987576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb938960048201526024016101c3565b61052d8383836001610d1f565b5f805f805f610a928787610d69565b9250925092505f80610aa48585610dc5565b9150915081838015610ab35750815b9650965050505050505b9250929050565b80471015610aee5760405163cf47918160e01b8152476004820152602481018290526044016101c3565b610b07828260405180602001604052805f815250610ce6565b15610b10575050565b3d1561092357610b1e610d14565b5050565b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b865181101561086e57868181518110610b8957610b89611831565b602002602001015193505f845f015160400151511115610cde575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001610c018d8a60200151610eb2565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401610c2c9190611eca565b5f60405180830381865afa158015610c46573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610c6d9190810190611fcb565b9150505f81511115610cdc5784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490610cae908a908590600401612081565b5f604051808303815f87803b158015610cc5575f80fd5b505af1158015610cd7573d5f803e3d5ffd5b505050505b505b600101610b6e565b5f805f83516020850186885af1949350505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f511483166109df5783831516156109d3573d5f823e3d81fd5b5f808060ff841681037f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff861115610db457600a860460018201600a88065f1493509350935050610dbe565b8593509150600190505b9250925092565b5f601b83900b8314838382610e29577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e1000000000000000000860515610e0957620186a0860595506005850194505b8586601b0b14610e2457600a86059550846001019450610e09565b610e3f565b855f03610e3f57505f925060019150610abd9050565b848560030b14610e82575f851215610e5f57505f9250829150610abd9050565b60405163d556b11160e01b815260048101839052602481018290526044016101c3565b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841660e084901b1791509250929050565b60605f825167ffffffffffffffff811115610ecf57610ecf6114be565b604051908082528060200260200182016040528015610ef8578160200160208202803683370190505b5090505f80845111610f0a575f610f10565b83516001015b85516001010190505f8167ffffffffffffffff811115610f3257610f326114be565b604051908082528060200260200182016040528015610f6557816020015b6060815260200190600190039081610f505790505b5090505f610f89604080516002815233602082015230818301526060810190915290565b828281518110610f9b57610f9b611831565b60200260200101819052505f5b8751811015610ff8578180600101925050878181518110610fcb57610fcb611831565b6020026020010151838381518110610fe557610fe5611831565b6020908102919091010152600101610fa8565b5085511561118a5780806001019150508382828151811061101b5761101b611831565b60200260200101819052505f5b8651811015611188576110d787828151811061104657611046611831565b60200260200101515f01516110b46110828a858151811061106957611069611831565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b8984815181106110c6576110c6611831565b602002602001015160400151611194565b6110f757604051630a57f30960e31b8152600481018290526024016101c3565b86818151811061110957611109611831565b60200260200101515f01516001600160a01b03165f1b85828151811061113157611131611831565b602002602001018181525050818060010192505086818151811061115757611157611831565b60200260200101516020015183838151811061117557611175611831565b6020908102919091010152600101611028565b505b5095945050505050565b5f836001600160a01b03163b5f036111f2575f806111b28585611204565b5090925090505f8160038111156111cb576111cb6120a1565b1480156111e95750856001600160a01b0316826001600160a01b0316145b9250505061093e565b6111fd84848461124a565b905061093e565b5f805f835160410361123b576020840151604085015160608601515f1a61122d8882858561129b565b955095509550505050610dbe565b505081515f9150600290610dbe565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156112d457505f91506003905082611359565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611325573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661135057505f925060019150829050611359565b92505f91508190505b9450945094915050565b5f60208284031215611373575f80fd5b81356001600160e01b03198116811461093e575f80fd5b6001600160a01b038116811461014e575f80fd5b5f805f805f8060a087890312156113b3575f80fd5b86356113be8161138a565b955060208701356113ce8161138a565b94506040870135935060608701359250608087013567ffffffffffffffff808211156113f8575f80fd5b818901915089601f83011261140b575f80fd5b813581811115611419575f80fd5b8a602082850101111561142a575f80fd5b6020830194508093505050509295509295509295565b5f805f60608486031215611452575f80fd5b833561145d8161138a565b9250602084013567ffffffffffffffff80821115611479575f80fd5b9085019060c0828803121561148c575f80fd5b909250604085013590808211156114a1575f80fd5b508401604081870312156114b3575f80fd5b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156114f5576114f56114be565b60405290565b6040805190810167ffffffffffffffff811182821017156114f5576114f56114be565b604051601f8201601f1916810167ffffffffffffffff81118282101715611547576115476114be565b604052919050565b5f67ffffffffffffffff821115611568576115686114be565b50601f01601f191660200190565b5f82601f830112611585575f80fd5b81356115986115938261154f565b61151e565b8181528460208386010111156115ac575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff8211156115e1576115e16114be565b5060051b60200190565b5f82601f8301126115fa575f80fd5b8135602061160a611593836115c8565b82815260059290921b84018101918181019086841115611628575f80fd5b8286015b8481101561172457803567ffffffffffffffff8082111561164b575f80fd5b908801906060828b03601f19011215611662575f80fd5b61166a6114d2565b868301356116778161138a565b81526040838101358381111561168b575f80fd5b8401603f81018d1361169b575f80fd5b888101356116ab611593826115c8565b81815260059190911b82018301908a8101908f8311156116c9575f80fd5b928401925b828410156116e75783358252928b0192908b01906116ce565b858c01525050506060840135838111156116ff575f80fd5b61170d8d8a83880101611576565b91830191909152508552505091830191830161162c565b509695505050505050565b5f6040823603121561173f575f80fd5b6117476114fb565b823567ffffffffffffffff8082111561175e575f80fd5b818501915060608236031215611772575f80fd5b61177a6114d2565b82356117858161138a565b815260208301356117958161138a565b60208201526040830135828111156117ab575f80fd5b6117b736828601611576565b604083015250835260208501359150808211156117d2575f80fd5b506117df368286016115eb565b60208301525092915050565b5f808335601e19843603018112611800575f80fd5b83018035915067ffffffffffffffff82111561181a575f80fd5b6020019150600581901b3603821315610abd575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112611859575f80fd5b9190910192915050565b5f8235609e19833603018112611859575f80fd5b5f808335601e1984360301811261188c575f80fd5b83018035915067ffffffffffffffff8211156118a6575f80fd5b6020019150600681901b3603821315610abd575f80fd5b5f602082840312156118cd575f80fd5b813561093e8161138a565b5f808335601e198436030181126118ed575f80fd5b830160208101925035905067ffffffffffffffff81111561190c575f80fd5b8060051b3603821315610abd575f80fd5b5f8235605e19833603018112611931575f80fd5b90910192915050565b5f808335601e1984360301811261194f575f80fd5b830160208101925035905067ffffffffffffffff81111561196e575f80fd5b803603821315610abd575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f808335601e198436030181126119b9575f80fd5b830160208101925035905067ffffffffffffffff8111156119d8575f80fd5b8060061b3603821315610abd575f80fd5b8183525f60208085019450825f5b85811015611a2f578135611a0a8161138a565b6001600160a01b031687528183013583880152604096870196909101906001016119f7565b509495945050505050565b8183526020808401935f91600585811b8301820185855b88811015611b1357858303601f19018a52611a6c828961191d565b60608135611a798161138a565b6001600160a01b03168552611a90828801836118d8565b82898801528083880152608092507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115611aca575f80fd5b871b808288850137860190506040611ae48482018561193a565b9450838884030182890152611afc848401868361197c565b9e8a019e9750505093870193505050600101611a51565b509098975050505050505050565b5f602080835260e08301843582850152604082860135818601526060818701358187015280870135801515808214611b57575f80fd5b8060808901525050611b6c60808801886118d8565b60c060a08901529384905261010093848801600582901b89018601835f5b84811015611ce8578b830360ff19018452813536879003607e19018112611baf575f80fd5b8601803536829003609e19018112611bc5575f80fd5b6080855281018035611bd68161138a565b6001600160a01b038082166080880152611bf28e84018461191d565b915060a0808801528135611c058161138a565b8116610120880152818e0135611c1a8161138a565b16610140870152611c2d818c018261193a565b91508a610160880152611c456101808801838361197c565b915050611c548b8301836119a4565b607f19808985030160c08a0152611c6c8483856119e9565b9350611c7a8d8601866119a4565b93509150808985030160e08a015250611c948383836119e9565b9250505060808201358c8701528c8301358d8701528a8301358b870152611cbd8a8401846118d8565b935091508581038a870152611cd3818484611a3a565b968d019695505050918a019150600101611b8a565b5050611cf760a08c018c61193a565b8b8303601f190160c08d015298509650611d1281898961197c565b9b9a5050505050505050505050565b5f8060408385031215611d32575f80fd5b505080516020909101519092909150565b5f805f60608486031215611d55575f80fd5b8351611d608161138a565b6020850151909350611d718161138a565b604085015190925067ffffffffffffffff811115611d8d575f80fd5b8401601f81018613611d9d575f80fd5b8051611dab6115938261154f565b818152876020838501011115611dbf575f80fd5b8160208401602083015e5f602083830101528093505050509250925092565b5f60208284031215611dee575f80fd5b815160ff8116811461093e575f80fd5b5f60208284031215611e0e575f80fd5b5051919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f815180845260208085019450602084015f5b83811015611a2f57815187529582019590820190600101611e56565b5f8282518085526020808601955060208260051b840101602086015f5b84811015611ebd57601f19868403018952611eab838351611e43565b98840198925090830190600101611e8f565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e06060840152611f03610100840182611e15565b9050606084015160808401526080840151601f19808584030160a0860152611f2b8383611e72565b925060a08601519150808584030160c0860152611f488383611e43565b925060c08601519150808584030160e086015250611f668282611e43565b95945050505050565b5f82601f830112611f7e575f80fd5b81516020611f8e611593836115c8565b8083825260208201915060208460051b870101935086841115611faf575f80fd5b602086015b848110156117245780518352918301918301611fb4565b5f8060408385031215611fdc575f80fd5b825167ffffffffffffffff80821115611ff3575f80fd5b818501915085601f830112612006575f80fd5b81516020612016611593836115c8565b82815260059290921b84018101918181019089841115612034575f80fd5b948201945b8386101561205257855182529482019490820190612039565b9188015191965090935050508082111561206a575f80fd5b5061207785828601611f6f565b9150509250929050565b828152604060208201525f6120996040830184611e43565b949350505050565b634e487b7160e01b5f52602160045260245ffd"; diff --git a/src/generated/GenericPoolRaindexV6FlashBorrower.pointers.sol b/src/generated/GenericPoolRaindexV6FlashBorrower.pointers.sol index 8932d45c12..8627becb8b 100644 --- a/src/generated/GenericPoolRaindexV6FlashBorrower.pointers.sol +++ b/src/generated/GenericPoolRaindexV6FlashBorrower.pointers.sol @@ -10,12 +10,12 @@ pragma solidity ^0.8.25; // file needs the contract to exist so that it can be compiled. /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0xed618063fd6ffc7558e4588ea6357356e781d660fa22caa292a2f9aeaa21996f); +bytes32 constant BYTECODE_HASH = bytes32(0x3438f85dace78d284e0eb33f8a245750498a37dfde867325a0760cf022e8fdb7); /// @dev The deterministic deploy address of the contract when deployed via /// the Zoltu factory. -address constant DEPLOYED_ADDRESS = address(0xAd8af7f90a06659E9bBFD457c6C642fB60B1F46b); +address constant DEPLOYED_ADDRESS = address(0x94e275d0eAf27c28C4737b91f8CD9D1DD9132019); /// @dev The runtime bytecode of the contract. bytes constant RUNTIME_CODE = - hex"608060405260043610610034575f3560e01c806301ffc9a71461003d57806323e30c8b146100715780638c18e4ba1461009e57005b3661003b57005b005b348015610048575f80fd5b5061005c6100573660046116eb565b6100b1565b60405190151581526020015b60405180910390f35b34801561007c575f80fd5b5061009061008b366004611774565b6100e7565b604051908152602001610068565b61003b6100ac3660046117eb565b610204565b5f6001600160e01b031982166323e30c8b60e01b14806100e157506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f337386594ac4319230870c6e587f4aca48fab575619e1461012257604051625e1e6f60e51b81523360048201526024015b60405180910390fd5b6001600160a01b0387163014610156576040516322c7df1960e21b81526001600160a01b0388166004820152602401610119565b5f8061016484860186611def565b915091506101728282610534565b6040516334e3942b60e11b815233906369c7285690610195908590600401612008565b60408051808303815f875af11580156101b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d49190612186565b507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd99a9950505050505050505050565b61020c6105a8565b61021b610218826121a8565b50565b6102286080850185612211565b90505f0361024957604051639c95219f60e01b815260040160405180910390fd5b6102596080850160608601612257565b61027657604051636d3a9fe560e01b815260040160405180910390fd5b5f84848460405160200161028c939291906124b0565b60408051601f1981840301815291905290505f6102ac6080870187612211565b5f8181106102bc576102bc6126c2565b90506020028101906102ce91906126d6565b6102d890806126f4565b6102e6906060810190612708565b6102f36080890189612211565b5f818110610303576103036126c2565b905060200281019061031591906126d6565b60400135818110610328576103286126c2565b61033e926020604090920201908101915061274e565b90505f61034e6080880188612211565b5f81811061035e5761035e6126c2565b905060200281019061037091906126d6565b61037a90806126f4565b610388906040810190612708565b61039560808a018a612211565b5f8181106103a5576103a56126c2565b90506020028101906103b791906126d6565b602001358181106103ca576103ca6126c2565b6103e0926020604090920201908101915061274e565b90505f6103ec826105d6565b90505f6103f8846105d6565b90505f6104068a358361065a565b905061041d6001600160a01b0385168c5f19610696565b6104326001600160a01b0386168c5f19610696565b604051632e7ff4ef60e11b81526001600160a01b038c1690635cffe9de90610464903090899086908c90600401612769565b6020604051808303815f875af1158015610480573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a4919061279a565b6104c1576040516349088f5960e11b815260040160405180910390fd5b6104d56001600160a01b0386168c5f610696565b6104e96001600160a01b0385168c5f610696565b6104fe6104f5886121a8565b85858886610710565b50505050505061052d60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5050505050565b5f82608001515f8151811061054b5761054b6126c2565b60200260200101515f01516060015183608001515f81518110610570576105706126c2565b6020026020010151604001518151811061058c5761058c6126c2565b60200260200101515f015190506105a381836109af565b505050565b6105b0610a59565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f6105df610a9d565b6040516354636d2b60e01b81526001600160a01b038316600482015273200e12d10bb0c5e4a17e7018f0f1161919bb9389906354636d2b906024016020604051808303815f875af1158015610636573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e191906127b5565b5f7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316601b0b60e084901d61068d828286610b28565b95945050505050565b6106a28383835f610b6c565b6105a3576106b383835f6001610b6c565b6106db57604051635274afe760e01b81526001600160a01b0384166004820152602401610119565b6106e88383836001610b6c565b6105a357604051635274afe760e01b81526001600160a01b0384166004820152602401610119565b6040805160018082528183019092525f91816020015b6060815260200190600190039081610726575050604080516003808252608082019092529192505f919060208201606080368337019050506040516370a0823160e01b81523060048201529091505f906001600160a01b038816906370a0823190602401602060405180830381865afa1580156107a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107c991906127d5565b905080156107e5576107e56001600160a01b0388163383610bce565b5f6107f08288610bdb565b50905080835f81518110610806576108066126c2565b602090810291909101015250506040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610857573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087b91906127d5565b90508015610897576108976001600160a01b0386163383610bce565b5f6108a28286610bdb565b50905080836001815181106108b9576108b96126c2565b60209081029190910101525047905080156108d8576108d83382610c1c565b5f6108e4826012610bdb565b50905080836002815181106108fb576108fb6126c2565b602002602001018181525050505080825f8151811061091c5761091c6126c2565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160a0810182525f918101828152606080830193909352608082018390528152602081019190915281526020019060019003908161093d57905050905087815f81518110610990576109906126c2565b60200260200101819052506109a58382610c93565b5050505050505050565b5f805f838060200190518101906109c691906127ec565b919450925090506001600160a01b0383166109f4576040516398521dc560e01b815260040160405180910390fd5b6001600160a01b038216610a1b5760405163456ac4c360e11b815260040160405180910390fd5b610a306001600160a01b038616845f19610696565b610a446001600160a01b0383168247610e57565b5061052d6001600160a01b038616845f610696565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054600203610a9b57604051633ee5aeb560e01b815260040160405180910390fd5b565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b1580610af4575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b15610a9b576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610119565b5f805f610b36868686610f05565b9150915080610b615760405162bc8ecf60e31b81526004810187905260248101869052604401610119565b5090505b9392505050565b60405163095ea7b360e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610bc2578383151615610bb6573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b6106e8838383600161106e565b5f805f805f610bea87876110b8565b9250925092505f80610bfc8585611114565b9150915081838015610c0b5750815b9650965050505050505b9250929050565b80471015610c465760405163cf47918160e01b815247600482015260248101829052604401610119565b610c5f828260405180602001604052805f815250611201565b15610c68575050565b3d15610c7a57610c76611216565b5050565b60405163d6bda27560e01b815260040160405180910390fd5b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b86518110156109a557868181518110610cfa57610cfa6126c2565b602002602001015193505f845f015160400151511115610e4f575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001610d728d8a60200151611221565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401610d9d91906128d2565b5f60405180830381865afa158015610db7573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610dde91908101906129ca565b9150505f81511115610e4d5784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490610e1f908a908590600401612a76565b5f604051808303815f87803b158015610e36575f80fd5b505af1158015610e48573d5f803e3d5ffd5b505050505b505b600101610cdf565b606081471015610e835760405163cf47918160e01b815247600482015260248101839052604401610119565b5f610e8f858486611201565b9050808015610eb057505f3d1180610eb057505f856001600160a01b03163b115b15610ec557610ebd611503565b915050610b65565b8015610eef57604051639996b31560e01b81526001600160a01b0386166004820152602401610119565b3d15610c7a57610efd611216565b509392505050565b5f805f851215610f3257604051634a7d166b60e01b81526004810186905260248101859052604401610119565b845f03610f4457505f90506001611066565b8460ff8416850185811215610f765760405163d556b11160e01b81526004810188905260248101879052604401610119565b5f805f831215610fc257604c19831215610f99575f809550955050505050611066565b825f03600a0a9150818481610fb057610fb0612a96565b04955050840290911491506110669050565b5f83131561105b57604d831315610fff5760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610119565b82600a0a9150815f198161101557611015612a96565b048411156110495760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610119565b50919091029250600191506110669050565b509193506001925050505b935093915050565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610bc2578383151615610bb6573d5f823e3d81fd5b5f808060ff841681037f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86111561110357600a860460018201600a88065f149350935093505061110d565b8593509150600190505b9250925092565b5f601b83900b8314838382611178577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e100000000000000000086051561115857620186a0860595506005850194505b8586601b0b1461117357600a86059550846001019450611158565b61118e565b855f0361118e57505f925060019150610c159050565b848560030b146111d1575f8512156111ae57505f9250829150610c159050565b60405163d556b11160e01b81526004810183905260248101829052604401610119565b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841660e084901b1791509250929050565b5f805f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b60605f825167ffffffffffffffff81111561123e5761123e611892565b604051908082528060200260200182016040528015611267578160200160208202803683370190505b5090505f80845111611279575f61127f565b83516001015b85516001010190505f8167ffffffffffffffff8111156112a1576112a1611892565b6040519080825280602002602001820160405280156112d457816020015b60608152602001906001900390816112bf5790505b5090505f6112f8604080516002815233602082015230818301526060810190915290565b82828151811061130a5761130a6126c2565b60200260200101819052505f5b875181101561136757818060010192505087818151811061133a5761133a6126c2565b6020026020010151838381518110611354576113546126c2565b6020908102919091010152600101611317565b508551156114f95780806001019150508382828151811061138a5761138a6126c2565b60200260200101819052505f5b86518110156114f7576114468782815181106113b5576113b56126c2565b60200260200101515f01516114236113f18a85815181106113d8576113d86126c2565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b898481518110611435576114356126c2565b60200260200101516040015161151c565b61146657604051630a57f30960e31b815260048101829052602401610119565b868181518110611478576114786126c2565b60200260200101515f01516001600160a01b03165f1b8582815181106114a0576114a06126c2565b60200260200101818152505081806001019250508681815181106114c6576114c66126c2565b6020026020010151602001518383815181106114e4576114e46126c2565b6020908102919091010152600101611397565b505b5095945050505050565b6040513d81523d5f602083013e3d602001810160405290565b5f836001600160a01b03163b5f0361157a575f8061153a858561158c565b5090925090505f81600381111561155357611553612aaa565b1480156115715750856001600160a01b0316826001600160a01b0316145b92505050610b65565b6115858484846115d2565b9050610b65565b5f805f83516041036115c3576020840151604085015160608601515f1a6115b588828585611623565b95509550955050505061110d565b505081515f915060029061110d565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561165c57505f915060039050826116e1565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156116ad573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166116d857505f9250600191508290506116e1565b92505f91508190505b9450945094915050565b5f602082840312156116fb575f80fd5b81356001600160e01b031981168114610b65575f80fd5b6001600160a01b0381168114610218575f80fd5b803561173181611712565b919050565b5f8083601f840112611746575f80fd5b50813567ffffffffffffffff81111561175d575f80fd5b602083019150836020828501011115610c15575f80fd5b5f805f805f8060a08789031215611789575f80fd5b863561179481611712565b955060208701356117a481611712565b94506040870135935060608701359250608087013567ffffffffffffffff8111156117cd575f80fd5b6117d989828a01611736565b979a9699509497509295939492505050565b5f805f805f608086880312156117ff575f80fd5b853561180a81611712565b9450602086013567ffffffffffffffff80821115611826575f80fd5b9087019060c0828a031215611839575f80fd5b9094506040870135908082111561184e575f80fd5b61185a89838a01611736565b90955093506060880135915080821115611872575f80fd5b50860160408189031215611884575f80fd5b809150509295509295909350565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156118c9576118c9611892565b60405290565b6040805190810167ffffffffffffffff811182821017156118c9576118c9611892565b6040516080810167ffffffffffffffff811182821017156118c9576118c9611892565b60405160a0810167ffffffffffffffff811182821017156118c9576118c9611892565b60405160c0810167ffffffffffffffff811182821017156118c9576118c9611892565b604051601f8201601f1916810167ffffffffffffffff8111828210171561198457611984611892565b604052919050565b8015158114610218575f80fd5b80356117318161198c565b5f67ffffffffffffffff8211156119bd576119bd611892565b5060051b60200190565b5f67ffffffffffffffff8211156119e0576119e0611892565b50601f01601f191660200190565b5f82601f8301126119fd575f80fd5b8135611a10611a0b826119c7565b61195b565b818152846020838601011115611a24575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608284031215611a50575f80fd5b611a586118a6565b90508135611a6581611712565b81526020820135611a7581611712565b6020820152604082013567ffffffffffffffff811115611a93575f80fd5b611a9f848285016119ee565b60408301525092915050565b5f82601f830112611aba575f80fd5b81356020611aca611a0b836119a4565b82815260069290921b84018101918181019086841115611ae8575f80fd5b8286015b84811015611b2e5760408189031215611b03575f80fd5b611b0b6118cf565b8135611b1681611712565b81528185013585820152835291830191604001611aec565b509695505050505050565b5f82601f830112611b48575f80fd5b81356020611b58611a0b836119a4565b82815260059290921b84018101918181019086841115611b76575f80fd5b8286015b84811015611b2e57803567ffffffffffffffff80821115611b99575f80fd5b908801906060828b03601f19011215611bb0575f80fd5b611bb86118a6565b86830135611bc581611712565b815260408381013583811115611bd9575f80fd5b8401603f81018d13611be9575f80fd5b88810135611bf9611a0b826119a4565b81815260059190911b82018301908a8101908f831115611c17575f80fd5b928401925b82841015611c355783358252928b0192908b0190611c1c565b858c0152505050606084013583811115611c4d575f80fd5b611c5b8d8a838801016119ee565b918301919091525085525050918301918301611b7a565b5f82601f830112611c81575f80fd5b81356020611c91611a0b836119a4565b82815260059290921b84018101918181019086841115611caf575f80fd5b8286015b84811015611b2e57803567ffffffffffffffff80821115611cd2575f80fd5b90880190601f196080838c0382011215611cea575f80fd5b611cf26118f2565b8784013583811115611d02575f80fd5b840160a0818e0384011215611d15575f80fd5b611d1d611915565b9250611d2a898201611726565b8352604081013584811115611d3d575f80fd5b611d4b8e8b83850101611a40565b8a8501525060608082013585811115611d62575f80fd5b611d708f8c83860101611aab565b604086015250608082013585811115611d87575f80fd5b611d958f8c83860101611aab565b828601525060a0820135608085015283835260408601358a8401528086013560408401526080860135935084841115611dcc575f80fd5b611dda8e8b86890101611b39565b90830152508652505050918301918301611cb3565b5f8060408385031215611e00575f80fd5b823567ffffffffffffffff80821115611e17575f80fd5b9084019060c08287031215611e2a575f80fd5b611e32611938565b823581526020830135602082015260408301356040820152611e5660608401611999565b6060820152608083013582811115611e6c575f80fd5b611e7888828601611c72565b60808301525060a083013582811115611e8f575f80fd5b611e9b888286016119ee565b60a08301525093506020850135915080821115611eb6575f80fd5b50611ec3858286016119ee565b9150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f815180845260208085019450602084015f5b83811015611f3e57815180516001600160a01b031688528301518388015260409096019590820190600101611f0e565b509495945050505050565b5f815180845260208085019450602084015f5b83811015611f3e57815187529582019590820190600101611f5c565b5f82825180855260208086019550808260051b8401018186015f5b84811015611ffb57601f19868403018952815160606001600160a01b038251168552858201518187870152611fca82870182611f49565b91505060408083015192508582038187015250611fe78183611ecd565b9a86019a9450505090830190600101611f93565b5090979650505050505050565b5f602080835260e08301845182850152818501516040818187015280870151915060608281880152808801519250608083151560808901526080890151935060a060c060a08a01528585518088526101009750878b019150878160051b8c010189880197505f5b82811015612157578c820360ff190184528851805187845280516001600160a01b03908116898601528d82015188860189905280518216610120870152808f01519091166101408601528a015161016085018a90526120d2610180860182611ecd565b90508a820151607f19808784030160c08801526120ef8383611efb565b92508b8401519150808784030160e08801525061210c8282611efb565b915050888201518d8601528d8301518e8601528a8301518b8601528983015192508481038a86015261213e8184611f78565b9b8e019b968e019694505050600191909101905061206f565b5060a08d01518c8203601f190160c08e01529950612175818b611ecd565b9d9c50505050505050505050505050565b5f8060408385031215612197575f80fd5b505080516020909101519092909150565b5f604082360312156121b8575f80fd5b6121c06118cf565b823567ffffffffffffffff808211156121d7575f80fd5b6121e336838701611a40565b835260208501359150808211156121f8575f80fd5b5061220536828601611b39565b60208301525092915050565b5f808335601e19843603018112612226575f80fd5b83018035915067ffffffffffffffff821115612240575f80fd5b6020019150600581901b3603821315610c15575f80fd5b5f60208284031215612267575f80fd5b8135610b658161198c565b5f808335601e19843603018112612287575f80fd5b830160208101925035905067ffffffffffffffff8111156122a6575f80fd5b8060051b3603821315610c15575f80fd5b5f8235605e198336030181126122cb575f80fd5b90910192915050565b5f808335601e198436030181126122e9575f80fd5b830160208101925035905067ffffffffffffffff811115612308575f80fd5b803603821315610c15575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f808335601e19843603018112612353575f80fd5b830160208101925035905067ffffffffffffffff811115612372575f80fd5b8060061b3603821315610c15575f80fd5b8183525f60208085019450825f5b85811015611f3e5781356123a481611712565b6001600160a01b03168752818301358388015260409687019690910190600101612391565b8183526020808401935f91600585811b8301820185855b888110156124a257858303601f19018a526123fb82896122b7565b6060813561240881611712565b6001600160a01b0316855261241f82880183612272565b82898801528083880152608092507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612459575f80fd5b871b808288850137860190506040612473848201856122d4565b945083888403018289015261248b8484018683612316565b9e8a019e97505050938701935050506001016123e0565b509098975050505050505050565b5f604080835261010080840187358386015260206060818a013581880152848a01356080880152808a01356124e48161198c565b151560a08801526124f860808b018b612272565b60c0898101529384905261012093848901600582901b8a018601835f5b84811015612672578c830361011f19018452813536879003607e1901811261253b575f80fd5b8601803536829003609e19018112612551575f80fd5b608085528101803561256281611712565b6001600160a01b03808216608088015261257e8c8401846122b7565b915060a080880152813561259181611712565b8116878e0152818c01356125a481611712565b166101408701526125b7818f01826122d4565b91508a6101608801526125cf61018088018383612316565b9150506125de8e83018361233e565b607f19808985030160c08a01526125f6848385612383565b93506126048d86018661233e565b93509150808985030160e08a01525061261e838383612383565b9250505060808201358d8701528a8301358b8701528d8301358e8701526126478a840184612272565b935091508581038a87015261265d8184846123c9565b968b0196955050509188019150600101612515565b505061268160a08f018f6122d4565b8c8303603f190160e08e01529950975061269c818a8a612316565b98505050505050858403818701525050506126b8818587612316565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f8235607e198336030181126126ea575f80fd5b9190910192915050565b5f8235609e198336030181126126ea575f80fd5b5f808335601e1984360301811261271d575f80fd5b83018035915067ffffffffffffffff821115612737575f80fd5b6020019150600681901b3603821315610c15575f80fd5b5f6020828403121561275e575f80fd5b8135610b6581611712565b5f6001600160a01b038087168352808616602084015250836040830152608060608301526126b86080830184611ecd565b5f602082840312156127aa575f80fd5b8151610b658161198c565b5f602082840312156127c5575f80fd5b815160ff81168114610b65575f80fd5b5f602082840312156127e5575f80fd5b5051919050565b5f805f606084860312156127fe575f80fd5b835161280981611712565b602085015190935061281a81611712565b604085015190925067ffffffffffffffff811115612836575f80fd5b8401601f81018613612846575f80fd5b8051612854611a0b826119c7565b818152876020838501011115612868575f80fd5b8160208401602083015e5f602083830101528093505050509250925092565b5f8282518085526020808601955060208260051b840101602086015f5b84811015611ffb57601f198684030189526128c0838351611f49565b988401989250908301906001016128a4565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e0606084015261290b610100840182611ecd565b9050606084015160808401526080840151601f19808584030160a08601526129338383612887565b925060a08601519150808584030160c08601526129508383611f49565b925060c08601519150808584030160e08601525061068d8282611f49565b5f82601f83011261297d575f80fd5b8151602061298d611a0b836119a4565b8083825260208201915060208460051b8701019350868411156129ae575f80fd5b602086015b84811015611b2e57805183529183019183016129b3565b5f80604083850312156129db575f80fd5b825167ffffffffffffffff808211156129f2575f80fd5b818501915085601f830112612a05575f80fd5b81516020612a15611a0b836119a4565b82815260059290921b84018101918181019089841115612a33575f80fd5b948201945b83861015612a5157855182529482019490820190612a38565b91880151919650909350505080821115612a69575f80fd5b50611ec38582860161296e565b828152604060208201525f612a8e6040830184611f49565b949350505050565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52602160045260245ffd"; + hex"608060405260043610610034575f3560e01c806301ffc9a71461003d57806323e30c8b146100715780638c18e4ba1461009e57005b3661003b57005b005b348015610048575f80fd5b5061005c6100573660046116eb565b6100b1565b60405190151581526020015b60405180910390f35b34801561007c575f80fd5b5061009061008b366004611774565b6100e7565b604051908152602001610068565b61003b6100ac3660046117eb565b610204565b5f6001600160e01b031982166323e30c8b60e01b14806100e157506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f337366f51a9c29480491c9282d99cf324e9f419a4e1d1461012257604051625e1e6f60e51b81523360048201526024015b60405180910390fd5b6001600160a01b0387163014610156576040516322c7df1960e21b81526001600160a01b0388166004820152602401610119565b5f8061016484860186611def565b915091506101728282610534565b6040516334e3942b60e11b815233906369c7285690610195908590600401612008565b60408051808303815f875af11580156101b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d49190612186565b507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd99a9950505050505050505050565b61020c6105a8565b61021b610218826121a8565b50565b6102286080850185612211565b90505f0361024957604051639c95219f60e01b815260040160405180910390fd5b6102596080850160608601612257565b61027657604051636d3a9fe560e01b815260040160405180910390fd5b5f84848460405160200161028c939291906124b0565b60408051601f1981840301815291905290505f6102ac6080870187612211565b5f8181106102bc576102bc6126c2565b90506020028101906102ce91906126d6565b6102d890806126f4565b6102e6906060810190612708565b6102f36080890189612211565b5f818110610303576103036126c2565b905060200281019061031591906126d6565b60400135818110610328576103286126c2565b61033e926020604090920201908101915061274e565b90505f61034e6080880188612211565b5f81811061035e5761035e6126c2565b905060200281019061037091906126d6565b61037a90806126f4565b610388906040810190612708565b61039560808a018a612211565b5f8181106103a5576103a56126c2565b90506020028101906103b791906126d6565b602001358181106103ca576103ca6126c2565b6103e0926020604090920201908101915061274e565b90505f6103ec826105d6565b90505f6103f8846105d6565b90505f6104068a358361065a565b905061041d6001600160a01b0385168c5f19610696565b6104326001600160a01b0386168c5f19610696565b604051632e7ff4ef60e11b81526001600160a01b038c1690635cffe9de90610464903090899086908c90600401612769565b6020604051808303815f875af1158015610480573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a4919061279a565b6104c1576040516349088f5960e11b815260040160405180910390fd5b6104d56001600160a01b0386168c5f610696565b6104e96001600160a01b0385168c5f610696565b6104fe6104f5886121a8565b85858886610710565b50505050505061052d60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5050505050565b5f82608001515f8151811061054b5761054b6126c2565b60200260200101515f01516060015183608001515f81518110610570576105706126c2565b6020026020010151604001518151811061058c5761058c6126c2565b60200260200101515f015190506105a381836109af565b505050565b6105b0610a59565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f6105df610a9d565b6040516354636d2b60e01b81526001600160a01b038316600482015273200e12d10bb0c5e4a17e7018f0f1161919bb9389906354636d2b906024016020604051808303815f875af1158015610636573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e191906127b5565b5f7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316601b0b60e084901d61068d828286610b28565b95945050505050565b6106a28383835f610b6c565b6105a3576106b383835f6001610b6c565b6106db57604051635274afe760e01b81526001600160a01b0384166004820152602401610119565b6106e88383836001610b6c565b6105a357604051635274afe760e01b81526001600160a01b0384166004820152602401610119565b6040805160018082528183019092525f91816020015b6060815260200190600190039081610726575050604080516003808252608082019092529192505f919060208201606080368337019050506040516370a0823160e01b81523060048201529091505f906001600160a01b038816906370a0823190602401602060405180830381865afa1580156107a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107c991906127d5565b905080156107e5576107e56001600160a01b0388163383610bce565b5f6107f08288610bdb565b50905080835f81518110610806576108066126c2565b602090810291909101015250506040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610857573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087b91906127d5565b90508015610897576108976001600160a01b0386163383610bce565b5f6108a28286610bdb565b50905080836001815181106108b9576108b96126c2565b60209081029190910101525047905080156108d8576108d83382610c1c565b5f6108e4826012610bdb565b50905080836002815181106108fb576108fb6126c2565b602002602001018181525050505080825f8151811061091c5761091c6126c2565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160a0810182525f918101828152606080830193909352608082018390528152602081019190915281526020019060019003908161093d57905050905087815f81518110610990576109906126c2565b60200260200101819052506109a58382610c93565b5050505050505050565b5f805f838060200190518101906109c691906127ec565b919450925090506001600160a01b0383166109f4576040516398521dc560e01b815260040160405180910390fd5b6001600160a01b038216610a1b5760405163456ac4c360e11b815260040160405180910390fd5b610a306001600160a01b038616845f19610696565b610a446001600160a01b0383168247610e57565b5061052d6001600160a01b038616845f610696565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054600203610a9b57604051633ee5aeb560e01b815260040160405180910390fd5b565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b1580610af4575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b15610a9b576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610119565b5f805f610b36868686610f05565b9150915080610b615760405162bc8ecf60e31b81526004810187905260248101869052604401610119565b5090505b9392505050565b60405163095ea7b360e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610bc2578383151615610bb6573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b6106e8838383600161106e565b5f805f805f610bea87876110b8565b9250925092505f80610bfc8585611114565b9150915081838015610c0b5750815b9650965050505050505b9250929050565b80471015610c465760405163cf47918160e01b815247600482015260248101829052604401610119565b610c5f828260405180602001604052805f815250611201565b15610c68575050565b3d15610c7a57610c76611216565b5050565b60405163d6bda27560e01b815260040160405180910390fd5b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b86518110156109a557868181518110610cfa57610cfa6126c2565b602002602001015193505f845f015160400151511115610e4f575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001610d728d8a60200151611221565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401610d9d91906128d2565b5f60405180830381865afa158015610db7573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610dde91908101906129ca565b9150505f81511115610e4d5784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490610e1f908a908590600401612a76565b5f604051808303815f87803b158015610e36575f80fd5b505af1158015610e48573d5f803e3d5ffd5b505050505b505b600101610cdf565b606081471015610e835760405163cf47918160e01b815247600482015260248101839052604401610119565b5f610e8f858486611201565b9050808015610eb057505f3d1180610eb057505f856001600160a01b03163b115b15610ec557610ebd611503565b915050610b65565b8015610eef57604051639996b31560e01b81526001600160a01b0386166004820152602401610119565b3d15610c7a57610efd611216565b509392505050565b5f805f851215610f3257604051634a7d166b60e01b81526004810186905260248101859052604401610119565b845f03610f4457505f90506001611066565b8460ff8416850185811215610f765760405163d556b11160e01b81526004810188905260248101879052604401610119565b5f805f831215610fc257604c19831215610f99575f809550955050505050611066565b825f03600a0a9150818481610fb057610fb0612a96565b04955050840290911491506110669050565b5f83131561105b57604d831315610fff5760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610119565b82600a0a9150815f198161101557611015612a96565b048411156110495760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610119565b50919091029250600191506110669050565b509193506001925050505b935093915050565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610bc2578383151615610bb6573d5f823e3d81fd5b5f808060ff841681037f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86111561110357600a860460018201600a88065f149350935093505061110d565b8593509150600190505b9250925092565b5f601b83900b8314838382611178577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e100000000000000000086051561115857620186a0860595506005850194505b8586601b0b1461117357600a86059550846001019450611158565b61118e565b855f0361118e57505f925060019150610c159050565b848560030b146111d1575f8512156111ae57505f9250829150610c159050565b60405163d556b11160e01b81526004810183905260248101829052604401610119565b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841660e084901b1791509250929050565b5f805f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b60605f825167ffffffffffffffff81111561123e5761123e611892565b604051908082528060200260200182016040528015611267578160200160208202803683370190505b5090505f80845111611279575f61127f565b83516001015b85516001010190505f8167ffffffffffffffff8111156112a1576112a1611892565b6040519080825280602002602001820160405280156112d457816020015b60608152602001906001900390816112bf5790505b5090505f6112f8604080516002815233602082015230818301526060810190915290565b82828151811061130a5761130a6126c2565b60200260200101819052505f5b875181101561136757818060010192505087818151811061133a5761133a6126c2565b6020026020010151838381518110611354576113546126c2565b6020908102919091010152600101611317565b508551156114f95780806001019150508382828151811061138a5761138a6126c2565b60200260200101819052505f5b86518110156114f7576114468782815181106113b5576113b56126c2565b60200260200101515f01516114236113f18a85815181106113d8576113d86126c2565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b898481518110611435576114356126c2565b60200260200101516040015161151c565b61146657604051630a57f30960e31b815260048101829052602401610119565b868181518110611478576114786126c2565b60200260200101515f01516001600160a01b03165f1b8582815181106114a0576114a06126c2565b60200260200101818152505081806001019250508681815181106114c6576114c66126c2565b6020026020010151602001518383815181106114e4576114e46126c2565b6020908102919091010152600101611397565b505b5095945050505050565b6040513d81523d5f602083013e3d602001810160405290565b5f836001600160a01b03163b5f0361157a575f8061153a858561158c565b5090925090505f81600381111561155357611553612aaa565b1480156115715750856001600160a01b0316826001600160a01b0316145b92505050610b65565b6115858484846115d2565b9050610b65565b5f805f83516041036115c3576020840151604085015160608601515f1a6115b588828585611623565b95509550955050505061110d565b505081515f915060029061110d565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561165c57505f915060039050826116e1565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156116ad573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166116d857505f9250600191508290506116e1565b92505f91508190505b9450945094915050565b5f602082840312156116fb575f80fd5b81356001600160e01b031981168114610b65575f80fd5b6001600160a01b0381168114610218575f80fd5b803561173181611712565b919050565b5f8083601f840112611746575f80fd5b50813567ffffffffffffffff81111561175d575f80fd5b602083019150836020828501011115610c15575f80fd5b5f805f805f8060a08789031215611789575f80fd5b863561179481611712565b955060208701356117a481611712565b94506040870135935060608701359250608087013567ffffffffffffffff8111156117cd575f80fd5b6117d989828a01611736565b979a9699509497509295939492505050565b5f805f805f608086880312156117ff575f80fd5b853561180a81611712565b9450602086013567ffffffffffffffff80821115611826575f80fd5b9087019060c0828a031215611839575f80fd5b9094506040870135908082111561184e575f80fd5b61185a89838a01611736565b90955093506060880135915080821115611872575f80fd5b50860160408189031215611884575f80fd5b809150509295509295909350565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156118c9576118c9611892565b60405290565b6040805190810167ffffffffffffffff811182821017156118c9576118c9611892565b6040516080810167ffffffffffffffff811182821017156118c9576118c9611892565b60405160a0810167ffffffffffffffff811182821017156118c9576118c9611892565b60405160c0810167ffffffffffffffff811182821017156118c9576118c9611892565b604051601f8201601f1916810167ffffffffffffffff8111828210171561198457611984611892565b604052919050565b8015158114610218575f80fd5b80356117318161198c565b5f67ffffffffffffffff8211156119bd576119bd611892565b5060051b60200190565b5f67ffffffffffffffff8211156119e0576119e0611892565b50601f01601f191660200190565b5f82601f8301126119fd575f80fd5b8135611a10611a0b826119c7565b61195b565b818152846020838601011115611a24575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608284031215611a50575f80fd5b611a586118a6565b90508135611a6581611712565b81526020820135611a7581611712565b6020820152604082013567ffffffffffffffff811115611a93575f80fd5b611a9f848285016119ee565b60408301525092915050565b5f82601f830112611aba575f80fd5b81356020611aca611a0b836119a4565b82815260069290921b84018101918181019086841115611ae8575f80fd5b8286015b84811015611b2e5760408189031215611b03575f80fd5b611b0b6118cf565b8135611b1681611712565b81528185013585820152835291830191604001611aec565b509695505050505050565b5f82601f830112611b48575f80fd5b81356020611b58611a0b836119a4565b82815260059290921b84018101918181019086841115611b76575f80fd5b8286015b84811015611b2e57803567ffffffffffffffff80821115611b99575f80fd5b908801906060828b03601f19011215611bb0575f80fd5b611bb86118a6565b86830135611bc581611712565b815260408381013583811115611bd9575f80fd5b8401603f81018d13611be9575f80fd5b88810135611bf9611a0b826119a4565b81815260059190911b82018301908a8101908f831115611c17575f80fd5b928401925b82841015611c355783358252928b0192908b0190611c1c565b858c0152505050606084013583811115611c4d575f80fd5b611c5b8d8a838801016119ee565b918301919091525085525050918301918301611b7a565b5f82601f830112611c81575f80fd5b81356020611c91611a0b836119a4565b82815260059290921b84018101918181019086841115611caf575f80fd5b8286015b84811015611b2e57803567ffffffffffffffff80821115611cd2575f80fd5b90880190601f196080838c0382011215611cea575f80fd5b611cf26118f2565b8784013583811115611d02575f80fd5b840160a0818e0384011215611d15575f80fd5b611d1d611915565b9250611d2a898201611726565b8352604081013584811115611d3d575f80fd5b611d4b8e8b83850101611a40565b8a8501525060608082013585811115611d62575f80fd5b611d708f8c83860101611aab565b604086015250608082013585811115611d87575f80fd5b611d958f8c83860101611aab565b828601525060a0820135608085015283835260408601358a8401528086013560408401526080860135935084841115611dcc575f80fd5b611dda8e8b86890101611b39565b90830152508652505050918301918301611cb3565b5f8060408385031215611e00575f80fd5b823567ffffffffffffffff80821115611e17575f80fd5b9084019060c08287031215611e2a575f80fd5b611e32611938565b823581526020830135602082015260408301356040820152611e5660608401611999565b6060820152608083013582811115611e6c575f80fd5b611e7888828601611c72565b60808301525060a083013582811115611e8f575f80fd5b611e9b888286016119ee565b60a08301525093506020850135915080821115611eb6575f80fd5b50611ec3858286016119ee565b9150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f815180845260208085019450602084015f5b83811015611f3e57815180516001600160a01b031688528301518388015260409096019590820190600101611f0e565b509495945050505050565b5f815180845260208085019450602084015f5b83811015611f3e57815187529582019590820190600101611f5c565b5f82825180855260208086019550808260051b8401018186015f5b84811015611ffb57601f19868403018952815160606001600160a01b038251168552858201518187870152611fca82870182611f49565b91505060408083015192508582038187015250611fe78183611ecd565b9a86019a9450505090830190600101611f93565b5090979650505050505050565b5f602080835260e08301845182850152818501516040818187015280870151915060608281880152808801519250608083151560808901526080890151935060a060c060a08a01528585518088526101009750878b019150878160051b8c010189880197505f5b82811015612157578c820360ff190184528851805187845280516001600160a01b03908116898601528d82015188860189905280518216610120870152808f01519091166101408601528a015161016085018a90526120d2610180860182611ecd565b90508a820151607f19808784030160c08801526120ef8383611efb565b92508b8401519150808784030160e08801525061210c8282611efb565b915050888201518d8601528d8301518e8601528a8301518b8601528983015192508481038a86015261213e8184611f78565b9b8e019b968e019694505050600191909101905061206f565b5060a08d01518c8203601f190160c08e01529950612175818b611ecd565b9d9c50505050505050505050505050565b5f8060408385031215612197575f80fd5b505080516020909101519092909150565b5f604082360312156121b8575f80fd5b6121c06118cf565b823567ffffffffffffffff808211156121d7575f80fd5b6121e336838701611a40565b835260208501359150808211156121f8575f80fd5b5061220536828601611b39565b60208301525092915050565b5f808335601e19843603018112612226575f80fd5b83018035915067ffffffffffffffff821115612240575f80fd5b6020019150600581901b3603821315610c15575f80fd5b5f60208284031215612267575f80fd5b8135610b658161198c565b5f808335601e19843603018112612287575f80fd5b830160208101925035905067ffffffffffffffff8111156122a6575f80fd5b8060051b3603821315610c15575f80fd5b5f8235605e198336030181126122cb575f80fd5b90910192915050565b5f808335601e198436030181126122e9575f80fd5b830160208101925035905067ffffffffffffffff811115612308575f80fd5b803603821315610c15575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f808335601e19843603018112612353575f80fd5b830160208101925035905067ffffffffffffffff811115612372575f80fd5b8060061b3603821315610c15575f80fd5b8183525f60208085019450825f5b85811015611f3e5781356123a481611712565b6001600160a01b03168752818301358388015260409687019690910190600101612391565b8183526020808401935f91600585811b8301820185855b888110156124a257858303601f19018a526123fb82896122b7565b6060813561240881611712565b6001600160a01b0316855261241f82880183612272565b82898801528083880152608092507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612459575f80fd5b871b808288850137860190506040612473848201856122d4565b945083888403018289015261248b8484018683612316565b9e8a019e97505050938701935050506001016123e0565b509098975050505050505050565b5f604080835261010080840187358386015260206060818a013581880152848a01356080880152808a01356124e48161198c565b151560a08801526124f860808b018b612272565b60c0898101529384905261012093848901600582901b8a018601835f5b84811015612672578c830361011f19018452813536879003607e1901811261253b575f80fd5b8601803536829003609e19018112612551575f80fd5b608085528101803561256281611712565b6001600160a01b03808216608088015261257e8c8401846122b7565b915060a080880152813561259181611712565b8116878e0152818c01356125a481611712565b166101408701526125b7818f01826122d4565b91508a6101608801526125cf61018088018383612316565b9150506125de8e83018361233e565b607f19808985030160c08a01526125f6848385612383565b93506126048d86018661233e565b93509150808985030160e08a01525061261e838383612383565b9250505060808201358d8701528a8301358b8701528d8301358e8701526126478a840184612272565b935091508581038a87015261265d8184846123c9565b968b0196955050509188019150600101612515565b505061268160a08f018f6122d4565b8c8303603f190160e08e01529950975061269c818a8a612316565b98505050505050858403818701525050506126b8818587612316565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f8235607e198336030181126126ea575f80fd5b9190910192915050565b5f8235609e198336030181126126ea575f80fd5b5f808335601e1984360301811261271d575f80fd5b83018035915067ffffffffffffffff821115612737575f80fd5b6020019150600681901b3603821315610c15575f80fd5b5f6020828403121561275e575f80fd5b8135610b6581611712565b5f6001600160a01b038087168352808616602084015250836040830152608060608301526126b86080830184611ecd565b5f602082840312156127aa575f80fd5b8151610b658161198c565b5f602082840312156127c5575f80fd5b815160ff81168114610b65575f80fd5b5f602082840312156127e5575f80fd5b5051919050565b5f805f606084860312156127fe575f80fd5b835161280981611712565b602085015190935061281a81611712565b604085015190925067ffffffffffffffff811115612836575f80fd5b8401601f81018613612846575f80fd5b8051612854611a0b826119c7565b818152876020838501011115612868575f80fd5b8160208401602083015e5f602083830101528093505050509250925092565b5f8282518085526020808601955060208260051b840101602086015f5b84811015611ffb57601f198684030189526128c0838351611f49565b988401989250908301906001016128a4565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e0606084015261290b610100840182611ecd565b9050606084015160808401526080840151601f19808584030160a08601526129338383612887565b925060a08601519150808584030160c08601526129508383611f49565b925060c08601519150808584030160e08601525061068d8282611f49565b5f82601f83011261297d575f80fd5b8151602061298d611a0b836119a4565b8083825260208201915060208460051b8701019350868411156129ae575f80fd5b602086015b84811015611b2e57805183529183019183016129b3565b5f80604083850312156129db575f80fd5b825167ffffffffffffffff808211156129f2575f80fd5b818501915085601f830112612a05575f80fd5b81516020612a15611a0b836119a4565b82815260059290921b84018101918181019089841115612a33575f80fd5b948201945b83861015612a5157855182529482019490820190612a38565b91880151919650909350505080821115612a69575f80fd5b50611ec38582860161296e565b828152604060208201525f612a8e6040830184611f49565b949350505050565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52602160045260245ffd"; diff --git a/src/generated/RaindexV6.pointers.sol b/src/generated/RaindexV6.pointers.sol index 27e8991640..a5d70f0227 100644 --- a/src/generated/RaindexV6.pointers.sol +++ b/src/generated/RaindexV6.pointers.sol @@ -10,16 +10,16 @@ pragma solidity ^0.8.25; // file needs the contract to exist so that it can be compiled. /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0x774ca4c194abf0720bca6c033580762029a80291feefd0a4b7855b16bcbbf7a9); +bytes32 constant BYTECODE_HASH = bytes32(0x670aa891cb8fcb7166ecf8031238f6287ead1ac018d6353af04dfd720b146e75); /// @dev The deterministic deploy address of the contract when deployed via /// the Zoltu factory. -address constant DEPLOYED_ADDRESS = address(0x86594ac4319230870C6E587f4ACa48FAb575619e); +address constant DEPLOYED_ADDRESS = address(0x66F51a9C29480491C9282D99cf324e9f419A4e1d); /// @dev The creation bytecode of the contract. bytes constant CREATION_CODE = - hex"6080604052348015600e575f80fd5b5060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055615eed806100405f395ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c8063613255ab11610093578063ac9650d811610063578063ac9650d81461022b578063d7e442ec1461024b578063d9d98ce41461025e578063fa50118214610271575f80fd5b8063613255ab146101ad57806369c72856146101c0578063709fb8a5146101e85780639235084d146101fb575f80fd5b80632fbc4ba0116100ce5780632fbc4ba01461015157806341d1514f146101665780635cffe9de14610187578063607461191461019a575f80fd5b806301ffc9a7146100f45780631f69cb751461011c5780632cb77e9f1461012f575b5f80fd5b6101076101023660046148e8565b610284565b60405190151581526020015b60405180910390f35b61010761012a366004614950565b6102ba565b61010761013d3660046149bb565b5f9081526020819052604090205460011490565b61016461015f3660046149f1565b6103c2565b005b610179610174366004614a56565b610521565b604051908152602001610113565b610107610195366004614a94565b610535565b6101646101a83660046149f1565b610635565b6101796101bb366004614b2b565b6107c8565b6101d36101ce366004614b5c565b610830565b60408051928352602083019190915201610113565b6101076101f6366004614b8e565b610fc9565b61020e610209366004614bd8565b61130c565b604080519315158452602084019290925290820152606001610113565b61023e610239366004614c0f565b6113ce565b6040516101139190614c7c565b610164610259366004614c0f565b6114b4565b61017961026c366004614cde565b61150e565b61016461027f366004615150565b6115a8565b5f6001600160e01b0319821663e414309160e01b14806102b457506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6102c3611a9a565b6102d06020850185614b2b565b6001600160a01b0316336001600160a01b03161461031f576102f56020850185614b2b565b6040516335252be360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b5f61033161032c8661520a565b611ab5565b5f818152602081905260409020549091505f19016103a4575f818152602081905260408082209190915551600192507f09d18501db0080ca2d6cd7c17fa7255daff4b2d503ea93b76ff68b6752ea8e639061039190339084908990615360565b60405180910390a16103a4818585611ae4565b506103bb60015f80516020615ecd83398151915255565b9392505050565b6103ca611a9a565b3385856103d8838383611b1b565b6103e2865f611b4c565b610417576040516306dde9c360e41b81523360048201526001600160a01b038916602482015260448101889052606401610316565b5f80610424338b8a611b86565b604080513381526001600160a01b038e1660208201529081018c90526060810183905291935091507f7f9dfa19cf1cc2f806f2f860fbc9c056b601fb1afc0e9b843dfe5c63616268e69060800160405180910390a15f80610487338d8d8d611c06565b909250905087156104fd5760408051600581526001600160a01b038e1660208201528082018d9052606081018490526080810183905260ff851660a082015260c081019091526104fd906104ee905b60408051600181526020810192909252818101905290565b6104f88a8c615424565b611cf6565b5050505050505061051a60015f80516020615ecd83398151915255565b5050505050565b5f61052d848484611ec4565b949350505050565b5f61054a6001600160a01b038616878661204e565b6040516323e30c8b60e01b81525f906001600160a01b038816906323e30c8b906105829033908a908a9087908b908b906004016154e4565b6020604051808303815f875af115801561059e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c29190615528565b90507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9811461060757604051630b6c58a960e31b815260048101829052602401610316565b61062887306106165f89615553565b6001600160a01b038a16929190612083565b5060019695505050505050565b61063d611a9a565b33858561064b838383611b1b565b5f8080806106598a82611b4c565b61068d57604051623a3a4d60e21b81523360048201526001600160a01b038d166024820152604481018c9052606401610316565b5f610699338e8e611ec4565b90506106a58b826120bf565b94506106b3338e8e886120db565b90935091505f6106c4338f88612152565b80965081925050507f8045c25080b0868951141ed0a91720bcad09a8364a2b3109ee1fd49c1f0bc8b8338f8f8f8a86604051610736969594939291906001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b60405180910390a1505060408051600681526001600160a01b038e1660208201528082018d9052606081018490526080810183905260a081018c905260ff851660c0820152600160e08201908152610100820182905261012082019092529089156107a9576107a9816104f88c8e615424565b50505050505050505061051a60015f80516020615ecd83398151915255565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa15801561080c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b49190615528565b5f8061083a611a9a565b6108476080840184615566565b90505f0361086857604051639c95219f60e01b815260040160405180910390fd5b610870614810565b61087861483c565b5f60405180606001604052808780608001906108949190615566565b5f8181106108a4576108a46155ac565b90506020028101906108b691906155c0565b6108c090806155de565b6108ce9060408101906155f2565b6108db60808b018b615566565b5f8181106108eb576108eb6155ac565b90506020028101906108fd91906155c0565b60200135818110610910576109106155ac565b6109269260206040909202019081019150614b2b565b6001600160a01b031681526020016109416080890189615566565b5f818110610951576109516155ac565b905060200281019061096391906155c0565b61096d90806155de565b61097b9060608101906155f2565b61098860808b018b615566565b5f818110610998576109986155ac565b90506020028101906109aa91906155c0565b604001358181106109bd576109bd6155ac565b6109d39260206040909202019081019150614b2b565b6001600160a01b03168152602088810135910152905060605f6109f96080890189615566565b604080516001909201602002820181528501519093505f9250610a1d915082611b4c565b610a3a5760405163315f9e2360e21b815260040160405180910390fd5b5f5b610a4960808a018a615566565b905081108015610a6357506040840151610a63905f611b4c565b15610e7157610a7560808a018a615566565b82818110610a8557610a856155ac565b9050602002810190610a9791906155c0565b610aa090615638565b9550855f01519450835f01516001600160a01b03168560400151876020015181518110610acf57610acf6155ac565b60200260200101515f01516001600160a01b0316141580610b2a575083602001516001600160a01b03168560600151876040015181518110610b1357610b136155ac565b60200260200101515f01516001600160a01b031614155b15610b485760405163936bb5ad60e01b815260040160405180910390fd5b610b5b85876020015188604001516121bb565b5f610b6586611ab5565b5f81815260208190526040902054909150610bca578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a1610e68565b5f610c278789602001518a60400151338c606001515f67ffffffffffffffff811115610bf857610bf8614d08565b604051908082528060200260200182016040528015610c21578160200160208202803683370190505b5061222d565b90505f610c458c604001358360600151611b4c90919063ffffffff16565b15610c9b578751604080513381526001600160a01b03909216602083015281018490527fe3151dc8cb7a54ffc4baabd28c1f241c94d510b5e5b502491ac3cad6c16316d5906060015b60405180910390a1610e5a565b6040820151610caa905f611b4c565b1580610cc257506060820151610cc0905f611b4c565b155b15610d0f578751604080513381526001600160a01b03909216602083015281018490527f500b713857325f9e6dcb52ae832eca9109d107ed1aae9cb4928b4c1e13f051aa90606001610c8e565b600190505f808d6060016020810190610d2891906156ce565b15610d6e576040808a015190850151610d40916120bf565b6060850151909250610d5290836126f2565b60408a0151909150610d64908361273f565b60408a0152610dd5565b5f610d8a856040015186606001516126f290919063ffffffff16565b9050610da38a60400151826120bf90919063ffffffff16565b9150610dbc85606001518361276f90919063ffffffff16565b60408b0151909350610dce908361273f565b60408b0152505b610ddf8c8261279f565b9b50610deb8d8361279f565b9c50610df782856127cf565b610e018185612890565b7f194f1feb3b4d7076a2c272e774e792e0c48bb8c7aa1a9a3671c1cd6da9e6b4c1338c8484604051610e3694939291906157f6565b60405180910390a187516001018089526020028801849052610e5784612a3c565b50505b8480610e635750805b945050505b50600101610a3c565b505f610e8360808a0160608b016156ce565b610e8d5786610e8f565b875b9050610e9c818a35612c7f565b15610ec45760405163573b6f4160e01b81528935600482015260248101829052604401610316565b50610ed433846020015189612152565b505f9050610ee560a08a018a6158e0565b9050118015610ef15750805b15610f635760208301518351339163691f9ed7918a8a610f1460a08f018f6158e0565b6040518763ffffffff1660e01b8152600401610f35969594939291906154e4565b5f604051808303815f87803b158015610f4c575f80fd5b505af1158015610f5e573d5f803e3d5ffd5b505050505b610f7133845f015188611b86565b50505f5b8251811015610fa857610fa0838281518110610f9357610f936155ac565b6020026020010151612cb9565b600101610f75565b505050505050610fc460015f80516020615ecd83398151915255565b915091565b5f610fd2611a9a565b5f61102f61102a610fe38780615923565b610ff19060408101906158e0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612dc392505050565b612e34565b90505f811161105157604051632cff108b60e21b815260040160405180910390fd5b6001811161107257604051633c8270bd60e21b815260040160405180910390fd5b61107f60208601866155f2565b90505f036110a057604051636c44ef8f60e01b815260040160405180910390fd5b6110ad60408601866155f2565b90505f036110ce5760405163540e5f0b60e01b815260040160405180910390fd5b6040805160a081019091523381525f90602081016110ec8880615923565b6110f590615937565b815260200187806020019061110a91906155f2565b808060200260200160405190810160405280939291908181526020015f905b828210156111555761114660408302860136819003810190615942565b81526020019060010190611129565b505050918352505060200161116d60408901896155f2565b808060200260200160405190810160405280939291908181526020015f905b828210156111b8576111a960408302860136819003810190615942565b8152602001906001019061118c565b50505050508152602001876060013581525090505f6111d682611ab5565b5f818152602081905260409020549091501580156112f1575f828152602081905260409081902060019055835190517f87491344dfbcf91f6cbbc610cbbeedc85313d37a02df0c93527f7ea5f8db717f91611234918590879061595c565b60405180910390a15f61124a60a08a018a6158e0565b905011156112e65761129b61126260a08a018a6158e0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612e4e92505050565b82517fd46c2c56b35c8210e9e712ec3f02242d5fc90187c0ac8ed80cc33626846ec36990836112cd60a08c018c6158e0565b6040516112dd9493929190615983565b60405180910390a15b6112f1828888611ae4565b93505050506103bb60015f80516020615ecd83398151915255565b5f80808061132661131d86806155de565b61032c9061520a565b5f8181526020819052604090205490915060011461134d57505f92508291508190506113c7565b61137261135a86806155de565b6113639061520a565b866020013587604001356121bb565b5f6113b061138087806155de565b6113899061520a565b60208801356040890135336113a160608c018c615566565b6113aa916159b5565b5f610bf8565b905060018160400151826060015194509450945050505b9193909250565b604080515f8152602081019091526060908267ffffffffffffffff8111156113f8576113f8614d08565b60405190808252806020026020018201604052801561142b57816020015b60608152602001906001900390816114165790505b5091505f5b838110156114ac576114873086868481811061144e5761144e6155ac565b905060200281019061146091906158e0565b85604051602001611473939291906159d4565b604051602081830303815290604052612e79565b838281518110611499576114996155ac565b6020908102919091010152600101611430565b505092915050565b6114bc611a9a565b604080515f808252602082019092526114f4916114e9565b60608152602001906001900390816114d45790505b506104f88385615424565b61150a60015f80516020615ecd83398151915255565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa158015611552573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115769190615528565b5f036115a057604051633c5bf76960e21b81526001600160a01b0384166004820152602401610316565b505f92915050565b6115b0611a9a565b835185516001600160a01b039182169116036115df57604051630a98f1f360e21b815260040160405180910390fd5b83604001518360400135815181106115f9576115f96155ac565b60200260200101515f01516001600160a01b03168560600151846020013581518110611627576116276155ac565b60200260200101515f01516001600160a01b03161415806116a0575060408501518051843590811061165b5761165b6155ac565b60200260200101515f01516001600160a01b03168460600151846060013581518110611689576116896155ac565b60200260200101515f01516001600160a01b031614155b156116be5760405163936bb5ad60e01b815260040160405180910390fd5b84606001518360200135815181106116d8576116d86155ac565b60200260200101515f01516001600160a01b03168560400151845f013581518110611705576117056155ac565b60200260200101515f01516001600160a01b03160361173757604051631cd2f1c760e21b815260040160405180910390fd5b5f61174186611ab5565b5f818152602081905260409020549091506117a7578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a150611a84565b5f6117b186611ab5565b5f81815260208190526040902054909150611818578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a15050611a84565b7f6fa7f4c28634b0a9d6831401c45ae468195fb63aed07308935c35374ff5d9e393388888860405161184d94939291906159f7565b60405180910390a1505083515f906118719087908635906020880135908686610bf8565b90505f6118a086866040013587606001358a5f0151885f67ffffffffffffffff811115610bf857610bf8614d08565b90505f6118ad8383612f19565b90506118bc815f0151846127cf565b6118ca8160200151836127cf565b6118d8816040015184612890565b6118e6816060015183612890565b6118ef83612cb9565b6118f882612cb9565b606081015181515f9161190b919061273f565b90505f6119298360400151846020015161273f90919063ffffffff16565b9050611935825f612c7f565b806119455750611945815f612c7f565b1561196357604051630d86822160e01b815260040160405180910390fd5b611997338b606001518a6020013581518110611981576119816155ac565b60200260200101515f01518a6080013585611c06565b50506119cd338a606001518a60600135815181106119b7576119b76155ac565b60200260200101515f01518a60a0013584611c06565b5050604080513381528451602080830191909152850151818301529084015160608083019190915284015160808201527fd9fa84dd790c969daa5c33d8050dc06b4a9b59d5b42e2be5f5e8ae20447f618d925060a001905060405180910390a1611a3683612a3c565b611a3f82612a3c565b80516001600160e01b0316158015611a62575060208101516001600160e01b0316155b15611a80576040516321badf1f60e01b815260040160405180910390fd5b5050505b61051a60015f80516020615ecd83398151915255565b611aa2612f67565b60025f80516020615ecd83398151915255565b5f81604051602001611ac79190615a73565b604051602081830303815290604052805190602001209050919050565b604080516002815260208101859052338183015260608101909152611b1690611b0c906104d6565b6104f88385615424565b505050565b80611b16576040516305dbdfd960e41b81526001600160a01b03808516600483015283166024820152604401610316565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d611b7a84848484612f98565b12979650505050505050565b5f805f611b928561306c565b9050611b9e845f612c7f565b15611bbc57604051632eaefac360e21b815260040160405180910390fd5b5f80611bc886846130d2565b9150915080611bdd57611bda82615a85565b91505b8115611bf857611bf86001600160a01b038816893085612083565b50925090505b935093915050565b5f80611c128382612c7f565b15611c335760405163793a8f5560e01b815260048101849052602401610316565b83611c5157611c43868685612152565b505f9250829150611ced9050565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611c8b828661279f565b9050611c97815f612c7f565b15611cb85760405163c5e12af560e01b815260048101829052602401610316565b6001600160a01b038089165f908152600160209081526040808320938b16835292815282822089835290522081905590925090505b94509492505050565b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b8651811015611eba57868181518110611d5d57611d5d6155ac565b602002602001015193505f845f015160400151511115611eb2575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001611dd58d8a602001516130ff565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401611e009190615af5565b5f60405180830381865afa158015611e1a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611e419190810190615bed565b9150505f81511115611eb05784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490611e82908a908590600401615ca3565b5f604051808303815f87803b158015611e99575f80fd5b505af1158015611eab573d5f803e3d5ffd5b505050505b505b600101611d42565b5050505050505050565b5f8115611efe57506001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546103bb565b5f611f08846133e1565b6040516370a0823160e01b81526001600160a01b0387811660048301529192505f91611f8091908716906370a0823190602401602060405180830381865afa158015611f56573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f7a9190615528565b836133ed565b50604051636eb1769f60e11b81526001600160a01b0388811660048301523060248301529192505f91611fff919088169063dd62ed3e90604401602060405180830381865afa158015611fd5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ff99190615528565b846133ed565b506001600160a01b038089165f908152600160209081526040808320938b168352928152828220828052905220549091506120449061203e84846120bf565b9061279f565b93505050506103bb565b61205b838383600161342d565b611b1657604051635274afe760e01b81526001600160a01b0384166004820152602401610316565b61209184848484600161348f565b6120b957604051635274afe760e01b81526001600160a01b0385166004820152602401610316565b50505050565b5f6120ca8383612c7f565b6120d457816103bb565b5090919050565b5f806120e78382612c7f565b156121085760405163793a8f5560e01b815260048101849052602401610316565b8361211857611c43868685611b86565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611c8b828661273f565b5f805f61215e8561306c565b905061216a845f612c7f565b1561218857604051632d1671a360e11b815260040160405180910390fd5b5f61219385836130d2565b50905080156121b0576121b06001600160a01b038716888361204e565b969095509350505050565b826060015181815181106121d1576121d16155ac565b60200260200101515f01516001600160a01b0316836040015183815181106121fb576121fb6155ac565b60200260200101515f01516001600160a01b031603611b1657604051631cd2f1c760e21b815260040160405180910390fd5b6122356148a3565b60408051600480825260a082019092526060915f9190816020015b60608152602001906001900390816122505790505090506122a56122738a611ab5565b8a51604080516003815260208101939093526001600160a01b0391821683820152908916606083015260808201905290565b8160018003815181106122ba576122ba6155ac565b60200260200101819052505f6122ef8a604001518a815181106122df576122df6155ac565b60200260200101515f01516133e1565b90505f6123418b5f01518c604001518c8151811061230f5761230f6155ac565b60200260200101515f01518d604001518d81518110612330576123306155ac565b602002602001015160200151611ec4565b90506123d08b604001518b8151811061235c5761235c6155ac565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d604001518d8151811061238e5761238e6155ac565b602002602001015160200151845f801b60408051600581526020810196909652858101949094526060850192909252608084015260a083015260c08201905290565b836001600303815181106123e6576123e66155ac565b602002602001018190525050505f61240d8a6060015189815181106122df576122df6155ac565b90505f61244e8b5f01518c606001518b8151811061242d5761242d6155ac565b60200260200101515f01518d606001518c81518110612330576123306155ac565b905061249b8b606001518a81518110612469576124696155ac565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d606001518c8151811061238e5761238e6155ac565b836001600403815181106124b1576124b16155ac565b602002602001018190525050506124c881866130ff565b9150505f885f01516001600160a01b031690505f808a602001515f01516001600160a01b031663d04dfe236040518060e001604052808e60200151602001516001600160a01b0316815260200161252887305f9182526020526040902090565b81526020018e602001516040015181526020015f81526020018781526020015f67ffffffffffffffff81111561256057612560614d08565b604051908082528060200260200182016040528015612589578160200160208202803683370190505b508152602001898152506040518263ffffffff1660e01b81526004016125af9190615af5565b5f60405180830381865afa1580156125c9573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125f09190810190615bed565b9150915060028251101561261c578151604051630fbb8e5560e21b815260040161031691815260200190565b602082015160408301518551612670908790600490811061263f5761263f6155ac565b6020026020010151600381518110612659576126596155ac565b6020026020010151826120bf90919063ffffffff16565b60408051600281526020810183905280820185905260608101909152909150866002815181106126a2576126a26155ac565b60200260200101819052506040518060e001604052808e81526020018c81526020018281526020018381526020018781526020018681526020018481525096505050505050509695505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d8480612722868686866134fc565b915091505f612731838361361b565b9a9950505050505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613668565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613692565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613bcf565b8181608001516004815181106127e7576127e76155ac565b6020026020010151600481518110612801576128016155ac565b6020026020010181815250506120b9815f01515f0151826080015160048151811061282e5761282e6155ac565b60200260200101515f81518110612847576128476155ac565b60200260200101515f1c8360800151600481518110612868576128686155ac565b6020026020010151600281518110612882576128826155ac565b6020026020010151856120db565b8181608001516003815181106128a8576128a86155ac565b60200260200101516004815181106128c2576128c26155ac565b6020908102919091010152805151608082015180515f919060039081106128eb576128eb6155ac565b60200260200101515f81518110612904576129046155ac565b60200260200101515f1c90505f8360800151600381518110612928576129286155ac565b6020026020010151600281518110612942576129426155ac565b602002602001015190505f801b81036129e95761295f855f612c7f565b156129805760405163793a8f5560e01b815260048101869052602401610316565b6001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546129b7908661279f565b6001600160a01b038085165f9081526001602090815260408083209387168352928152828220858352905220556129f8565b6129f583838388611c06565b50505b7f4cb6e22a3e7e651d7cf0376cff48f20f5007a54147777865be7f5f6c38c50f4a338560800151604051612a2d929190615cbb565b60405180910390a15050505050565b60c08101515115612ab6578051602090810151015160a082015160c083015160405163012c676d60e21b81526001600160a01b03909316926304b19db492612a88929091600401615ca3565b5f604051808303815f87803b158015612a9f575f80fd5b505af1158015612ab1573d5f803e3d5ffd5b505050505b5f815f0151602001515f01516001600160a01b031663d04dfe236040518060e00160405280855f015160200151602001516001600160a01b03168152602001612b0c8660a00151305f9182526020526040902090565b8152602001855f01516020015160400151815260200160018152602001856080015181526020015f67ffffffffffffffff811115612b4c57612b4c614d08565b604051908082528060200260200182016040528015612b75578160200160208202803683370190505b5081526020015f604051908082528060200260200182016040528015612ba5578160200160208202803683370190505b508152506040518263ffffffff1660e01b8152600401612bc59190615af5565b5f60405180830381865afa158015612bdf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612c069190810190615bed565b9150505f8151111561150a578151602090810151015160a083015160405163012c676d60e21b81526001600160a01b03909216916304b19db491612c4e918590600401615ca3565b5f604051808303815f87803b158015612c65575f80fd5b505af1158015612c77573d5f803e3d5ffd5b505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d612cad84848484612f98565b13979650505050505050565b5f8160800151600381518110612cd157612cd16155ac565b6020026020010151600281518110612ceb57612ceb6155ac565b602002602001015190505f801b810361150a57815151608083015180515f91906003908110612d1c57612d1c6155ac565b60200260200101515f81518110612d3557612d356155ac565b6020908102919091018101516001600160a01b038481165f9081526001845260408082209284168252918452818120878252909352909120549091506001600160e01b0381161561051a576001600160a01b038084165f9081526001602090815260408083209386168352928152828220878352905290812055612dba838383612152565b50505050505050565b6060604082511015612de257505060408051602081019091525f815290565b5f60208301519050602060408451612dfa91906159c1565b612e049190615cf0565b811115612e2057505060408051602081019091525f8152919050565b600181016020026020840101915050919050565b5f81515f03612e4457505f919050565b50602001515f1a90565b612e5781613ccd565b612e765780604051630c89984b60e31b81526004016103169190615d0f565b50565b60605f612e868484613cfb565b9050808015612ea757505f3d1180612ea757505f846001600160a01b03163b115b15612ebc57612eb4613d0e565b9150506102b4565b8015612ee657604051639996b31560e01b81526001600160a01b0385166004820152602401610316565b3d15612ef957612ef4613d27565b612f12565b60405163d6bda27560e01b815260040160405180910390fd5b5092915050565b604080516080810182525f808252602082018190529181018290526060810191909152612f468383613d32565b82526040820152612f578284613d32565b6020830152606082015292915050565b5f80516020615ecd83398151915254600203612f9657604051633ee5aeb560e01b815260040160405180910390fd5b565b5f8085158415178187128286121817858414178015612fbd5786859250925050611ced565b505f85841315612fd1575092949193919260015b8386035f8112604c8213178015613004578215612ff6575f8994509450505050611ced565b885f94509450505050611ced565b600a82900a8981028a82828161301c5761301c615cdc565b0514613048578415613038575f8b965096505050505050611ced565b8a5f965096505050505050611ced565b841561305d578896509450611ced9350505050565b9550879450611ced9350505050565b5f805f61307884613d9b565b9092509050600182600381111561309157613091615d21565b141580156130b057505f8260038111156130ad576130ad615d21565b14155b156103bb57838260405163ee07877f60e01b8152600401610316929190615d35565b5f806001600160e01b038416601b0b60e085901d6130f1828287613e28565b9350935050505b9250929050565b60605f825167ffffffffffffffff81111561311c5761311c614d08565b604051908082528060200260200182016040528015613145578160200160208202803683370190505b5090505f80845111613157575f61315d565b83516001015b85516001010190505f8167ffffffffffffffff81111561317f5761317f614d08565b6040519080825280602002602001820160405280156131b257816020015b606081526020019060019003908161319d5790505b5090505f6131d6604080516002815233602082015230818301526060810190915290565b8282815181106131e8576131e86155ac565b60200260200101819052505f5b8751811015613245578180600101925050878181518110613218576132186155ac565b6020026020010151838381518110613232576132326155ac565b60209081029190910101526001016131f5565b508551156133d757808060010191505083828281518110613268576132686155ac565b60200260200101819052505f5b86518110156133d557613324878281518110613293576132936155ac565b60200260200101515f01516133016132cf8a85815181106132b6576132b66155ac565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b898481518110613313576133136155ac565b602002602001015160400151613f8e565b61334457604051630a57f30960e31b815260048101829052602401610316565b868181518110613356576133566155ac565b60200260200101515f01516001600160a01b03165f1b85828151811061337e5761337e6155ac565b60200260200101818152505081806001019250508681815181106133a4576133a46155ac565b6020026020010151602001518383815181106133c2576133c26155ac565b6020908102919091010152600101613275565b505b5095945050505050565b5f805f61307884613ffe565b5f805f805f6133fc878761405d565b9250925092505f8061340e85856140a0565b915091508183801561341d5750815b9650965050505050509250929050565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316613483578383151615613477573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b6040516323b872dd60e01b5f8181526001600160a01b038781166004528616602452604485905291602083606481808c5af1925060015f511483166134eb5783831516156134df573d5f823e3d81fd5b5f883b113d1516831692505b604052505f60605295945050505050565b5f8085158415178015613514575f92505f9150613611565b61351e8487615d6e565b91505f61352a88614178565b90505f61353687614178565b90505f61354383836141a6565b5090505f6f0785ee10d5da46d900f436a000000000821115613578576f0785ee10d5da46d900f436a000000000820491506025015b670de0b6b3a764000082111561359957670de0b6b3a7640000820491506012015b633b9aca008211156135b257633b9aca00820491506009015b6127108211156135c757612710820491506004015b81156135db57600a820491506001016135c7565b6135e58187615d6e565b95506136078b8a61360187876135fc87600a615e6d565b6141c2565b8961428e565b9097509550505050505b5094509492505050565b5f805f61362885856140a0565b9150915080158015613638575081155b1561366057604051638eba4d0760e01b81526004810186905260248101859052604401610316565b509392505050565b5f80613674848461432e565b909450925061368586868686613bcf565b9150915094509492505050565b5f80835f036136be57604051637a97930f60e01b81526004810187905260248101869052604401610316565b855f036136cf57505f905080611ced565b5f805f806136dd8a8a614383565b919b50995091506136ee8888614383565b919950975090505f6136ff8b614178565b90505f61370b8a614178565b90507f161bcca7119915b50764b4abe86529797775a5f1719510000000000000000000604c81831015613ad057841561376257507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b9050604b613aa8565b6f4b3b4ca85a86c47a098a22400000000083101561388e57678ac7230489e800008310156137f2576402540be4008310156137c057620186a08310156137b05750620186a090506005613a69565b506402540be4009050600a613a69565b655af3107a40008310156137df5750655af3107a40009050600e613a69565b50678ac7230489e8000090506013613a69565b6b204fce5e3e250261100000008310156138445769152d02c7e14af680000083101561382d575069152d02c7e14af680000090506017613a69565b506b204fce5e3e250261100000009050601c613a69565b6d314dc6448d9338c15b0a0000000083101561387357506d314dc6448d9338c15b0a0000000090506021613a69565b506f4b3b4ca85a86c47a098a22400000000090506026613a69565b780197d4df19d605767337e9f14d3eec8920e4000000000000008310156139865773af298d050e4395d69670b12b7f41000000000000831015613921577172cb5bd86321e38cb6ce6682e8000000000083101561390257507172cb5bd86321e38cb6ce6682e800000000009050602b613a69565b5073af298d050e4395d69670b12b7f4100000000000090506030613a69565b76010b46c6cdd6e3e0828f4db456ff0c8ea0000000000000831015613962575076010b46c6cdd6e3e0828f4db456ff0c8ea000000000000090506035613a69565b50780197d4df19d605767337e9f14d3eec8920e4000000000000009050603a613a69565b7c03b58e88c75313ec9d329eaaa18fb92f75215b17100000000000000000831015613a1c577a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000008310156139f457507a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000009050603f613a69565b507c03b58e88c75313ec9d329eaaa18fb92f75215b1710000000000000000090506044613a69565b7e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000831015613a6957507e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000905060495b818311613a7e57600a820491505f1901613a69565b815f03613aa8576040516305e51ecb60e01b8152600481018d9052602481018c9052604401610316565b85613ad0576040516305e51ecb60e01b8152600481018f9052602481018e9052604401610316565b80600160ff1b018d12613ae757808d039c50613b25565b600160ff1b9c90038c015f811315613b2557806001600160ff1b03038b13613b1257998a0199613b25565b5f80995099505050505050505050611ced565b5f808e128015613b3457505f8c135b15613b5557600160ff1b8e01808d13613b4d575f613b51565b808d035b9150505b8b818f01039750613b728f8e613b6c8887896141c2565b8b61428e565b90995097505f811315613bbc57604c811315613b9c575f809a509a50505050505050505050611ced565b80600a0a8981613bae57613bae615cdc565b059850885f03613bbc575f97505b50969850949650611ced95505050505050565b5f8085158415178015613bfb57865f03613bef5784849250925050611ced565b86869250925050611ced565b613c0587876145dd565b9097509550613c1485856145dd565b909550935085841315613c28579395929492935b838603604c811115613c41578787935093505050611ced565b80600a0a8681613c5357613c53615cdc565b0595505086850180881860ff90811c151589881890911c15168015613cbc57876001600160ff1b0303613ca35760405163d556b11160e01b8152600481018a905260248101899052604401610316565b600a968790059690980586019760019790970196613cc0565b8198505b5096979596505050505050565b5f600882511015613cdf57505f919050565b506008015167ffffffffffffffff1667ff0a89c674ee78741490565b5f805f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f80613d4f846060015185604001516126f290919063ffffffff16565b915083604001519050613d6f836040015183611b4c90919063ffffffff16565b156130f85782604001519150613d9284606001518361276f90919063ffffffff16565b90509250929050565b5f80613da5614626565b60405163b7bad1b160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb93899063b7bad1b19060240160408051808303815f875af1158015613dfb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e1f9190615e78565b91509150915091565b5f805f851215613e5557604051634a7d166b60e01b81526004810186905260248101859052604401610316565b845f03613e6757505f90506001611bfe565b8460ff8416850185811215613e995760405163d556b11160e01b81526004810188905260248101879052604401610316565b5f805f831215613ee557604c19831215613ebc575f809550955050505050611bfe565b825f03600a0a9150818481613ed357613ed3615cdc565b0495505084029091149150611bfe9050565b5f831315613f7e57604d831315613f225760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b82600a0a9150815f1981613f3857613f38615cdc565b04841115613f6c5760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b5091909102925060019150611bfe9050565b8360019550955050505050611bfe565b5f836001600160a01b03163b5f03613fec575f80613fac85856146b1565b5090925090505f816003811115613fc557613fc5615d21565b148015613fe35750856001600160a01b0316826001600160a01b0316145b925050506103bb565b613ff78484846146f7565b90506103bb565b5f80614008614626565b604051630782d7e160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb938990630782d7e1906024016040805180830381865afa158015613dfb573d5f803e3d5ffd5b5f808060ff841681036001600160ff1b0386111561408f57600a860460018201600a88065f1493509350935050614099565b8593509150600190505b9250925092565b5f601b83900b8314838382614104577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e10000000000000000008605156140e457620186a0860595506005850194505b8586601b0b146140ff57600a860595508460010194506140e4565b61411a565b855f0361411a57505f9250600191506130f89050565b848560030b1461415d575f85121561413a57505f92508291506130f89050565b60405163d556b11160e01b81526004810183905260248101829052604401610316565b50506001600160e01b03841660e084901b1791509250929050565b5f8082121561419d57600160ff1b82036141975750600160ff1b919050565b505f0390565b5090565b919050565b5f805f1983850993909202808410938190039390930393915050565b5f805f6141cf86866141a6565b91509150815f036141f3578381816141e9576141e9615cdc565b04925050506103bb565b8382106142245760405163362ced0960e11b8152600481018790526024810186905260448101859052606401610316565b5f84868809600186198101871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103025f82900382900490920185841190960395909502919093039390930492909217029150509392505050565b5f805f858718121561430a576001600160ff1b038411156142f7576142bb6001600160ff1b036001615553565b84036142cf5750600160ff1b905081611ced565b6142da600a85615cf0565b6142e390615eb8565b6142ee846001615d6e565b91509150611ced565b61430084615eb8565b8391509150611ced565b6001600160ff1b03841115614324576142e3600a85615cf0565b5082905081611ced565b5f80600160ff1b8403614379576001600160ff1b03830361436c5760405163d556b11160e01b81526004810185905260248101849052604401610316565b600a840593508260010192505b50505f9190910391565b5f805f845f0361439b57505f91508190506001614099565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85055f03614588576f4b3b4ca85a86c47a098a22400000000085051580156143fd57507f80000000000000000000000000000000000000000000000000000000000000268412155b1561441e576f4b3b4ca85a86c47a098a224000000000850294506026840393505b7728c87cb5c89a2571ebfdcb54864ada834a00000000000000850515801561446657507f80000000000000000000000000000000000000000000000000000000000000138412155b1561447f57678ac7230489e80000850294506013840393505b7b097edd871cfda3a5697758bf0e3cbb5ac5741c64000000000000000085051580156144cb57507f800000000000000000000000000000000000000000000000000000000000000a8412155b156144e1576402540be40085029450600a840393505b7e3899162693736ac531a5a58f1fbb4b746504382ca7e4000000000000000000850515801561453057507f80000000000000000000000000000000000000000000000000000000000000028412155b15614546576064850294506002840393506144e1565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b850515801561457657506001600160ff1b018412155b1561458857600a850294506001840393505b600a808602908105861480156145a557506001600160ff1b018512155b156145b4578095506001850394505b50939492935050507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b8305151590565b5f805f805f6145ec8787614383565b9250925092508061461a576040516305e51ecb60e01b81526004810188905260248101879052604401610316565b50909590945092505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b158061467d575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b15612f96576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610316565b5f805f83516041036146e8576020840151604085015160608601515f1a6146da88828585614748565b955095509550505050614099565b505081515f9150600290614099565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561478157505f91506003905082614806565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156147d2573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166147fd57505f925060019150829050614806565b92505f91508190505b9450945094915050565b604051806080016040528061482361483c565b81526020015f81526020015f8152602001606081525090565b6040518060a001604052805f6001600160a01b0316815260200161488a60405180606001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b8152606060208201819052604082018190525f91015290565b6040518060e001604052806148b661483c565b81526020015f81526020015f80191681526020015f8019168152602001606081526020015f8152602001606081525090565b5f602082840312156148f8575f80fd5b81356001600160e01b0319811681146103bb575f80fd5b5f8083601f84011261491f575f80fd5b50813567ffffffffffffffff811115614936575f80fd5b6020830191508360208260051b85010111156130f8575f80fd5b5f805f60408486031215614962575f80fd5b833567ffffffffffffffff80821115614979575f80fd5b9085019060a0828803121561498c575f80fd5b909350602085013590808211156149a1575f80fd5b506149ae8682870161490f565b9497909650939450505050565b5f602082840312156149cb575f80fd5b5035919050565b6001600160a01b0381168114612e76575f80fd5b80356141a1816149d2565b5f805f805f60808688031215614a05575f80fd5b8535614a10816149d2565b94506020860135935060408601359250606086013567ffffffffffffffff811115614a39575f80fd5b614a458882890161490f565b969995985093965092949392505050565b5f805f60608486031215614a68575f80fd5b8335614a73816149d2565b92506020840135614a83816149d2565b929592945050506040919091013590565b5f805f805f60808688031215614aa8575f80fd5b8535614ab3816149d2565b94506020860135614ac3816149d2565b935060408601359250606086013567ffffffffffffffff80821115614ae6575f80fd5b818801915088601f830112614af9575f80fd5b813581811115614b07575f80fd5b896020828501011115614b18575f80fd5b9699959850939650602001949392505050565b5f60208284031215614b3b575f80fd5b81356103bb816149d2565b5f60c08284031215614b56575f80fd5b50919050565b5f60208284031215614b6c575f80fd5b813567ffffffffffffffff811115614b82575f80fd5b61052d84828501614b46565b5f805f60408486031215614ba0575f80fd5b833567ffffffffffffffff80821115614bb7575f80fd5b614bc387838801614b46565b945060208601359150808211156149a1575f80fd5b5f60208284031215614be8575f80fd5b813567ffffffffffffffff811115614bfe575f80fd5b8201608081850312156103bb575f80fd5b5f8060208385031215614c20575f80fd5b823567ffffffffffffffff811115614c36575f80fd5b614c428582860161490f565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614cd157603f19888603018452614cbf858351614c4e565b94509285019290850190600101614ca3565b5092979650505050505050565b5f8060408385031215614cef575f80fd5b8235614cfa816149d2565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b60405290565b6040805190810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b60405160a0810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b604051601f8201601f1916810167ffffffffffffffff81118282101715614db457614db4614d08565b604052919050565b5f82601f830112614dcb575f80fd5b813567ffffffffffffffff811115614de557614de5614d08565b614df8601f8201601f1916602001614d8b565b818152846020838601011115614e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608284031215614e38575f80fd5b614e40614d1c565b90508135614e4d816149d2565b81526020820135614e5d816149d2565b6020820152604082013567ffffffffffffffff811115614e7b575f80fd5b614e8784828501614dbc565b60408301525092915050565b5f67ffffffffffffffff821115614eac57614eac614d08565b5060051b60200190565b5f60408284031215614ec6575f80fd5b614ece614d45565b90508135614edb816149d2565b808252506020820135602082015292915050565b5f82601f830112614efe575f80fd5b81356020614f13614f0e83614e93565b614d8b565b8083825260208201915060208460061b870101935086841115614f34575f80fd5b602086015b84811015614f5957614f4b8882614eb6565b835291830191604001614f39565b509695505050505050565b5f60a08284031215614f74575f80fd5b614f7c614d68565b9050614f87826149e6565b8152602082013567ffffffffffffffff80821115614fa3575f80fd5b614faf85838601614e28565b60208401526040840135915080821115614fc7575f80fd5b614fd385838601614eef565b60408401526060840135915080821115614feb575f80fd5b50614ff884828501614eef565b6060830152506080820135608082015292915050565b5f61501b614f0e84614e93565b8381529050602080820190600585811b850187811115615039575f80fd5b855b8181101561512657803567ffffffffffffffff8082111561505a575f80fd5b908801906060828c03121561506d575f80fd5b615075614d1c565b8235615080816149d2565b81528287013582811115615092575f80fd5b8301601f81018d136150a2575f80fd5b80356150b0614f0e82614e93565b81815290881b8201890190898101908f8311156150cb575f80fd5b928a01925b828410156150e95783358252928a0192908a01906150d0565b848b01525060409150508381013583811115615103575f80fd5b61510f8e828701614dbc565b91830191909152508752505093830193830161503b565b50505050509392505050565b5f82601f830112615141575f80fd5b6103bb8383356020850161500e565b5f805f805f6101408688031215615165575f80fd5b853567ffffffffffffffff8082111561517c575f80fd5b61518889838a01614f64565b9650602088013591508082111561519d575f80fd5b6151a989838a01614f64565b95506151b88960408a01614b46565b94506101008801359150808211156151ce575f80fd5b6151da89838a01615132565b93506101208801359150808211156151f0575f80fd5b506151fd88828901615132565b9150509295509295909350565b5f6102b43683614f64565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f8135615249816149d2565b6001600160a01b039081168452602083013590615265826149d2565b166020840152604082013536839003601e19018112615282575f80fd5b820160208101903567ffffffffffffffff81111561529e575f80fd5b8036038213156152ac575f80fd5b606060408601526152c1606086018284615215565b95945050505050565b5f808335601e198436030181126152df575f80fd5b830160208101925035905067ffffffffffffffff8111156152fe575f80fd5b8060061b36038213156130f8575f80fd5b8183525f60208085019450825f5b85811015615355578135615330816149d2565b6001600160a01b0316875281830135838801526040968701969091019060010161531d565b509495945050505050565b5f6001600160a01b038086168352846020840152606060408401528335615386816149d2565b166060830152602083013536849003605e190181126153a3575f80fd5b60a060808401526153ba610100840185830161523d565b90506153c960408501856152ca565b605f19808685030160a08701526153e184838561530f565b93506153f060608801886152ca565b93509150808685030160c08701525061540a83838361530f565b92505050608084013560e084015280915050949350505050565b5f615431614f0e84614e93565b80848252602080830192508560051b85013681111561544e575f80fd5b855b818110156154d857803567ffffffffffffffff8082111561546f575f80fd5b818901915060408236031215615483575f80fd5b61548b614d45565b823582811115615499575f80fd5b6154a536828601614e28565b82525085830135828111156154b8575f80fd5b6154c436828601615132565b828801525087525050938201938201615450565b50919695505050505050565b5f6001600160a01b03808916835280881660208401525085604083015284606083015260a0608083015261551c60a083018486615215565b98975050505050505050565b5f60208284031215615538575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102b4576102b461553f565b5f808335601e1984360301811261557b575f80fd5b83018035915067ffffffffffffffff821115615595575f80fd5b6020019150600581901b36038213156130f8575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e198336030181126155d4575f80fd5b9190910192915050565b5f8235609e198336030181126155d4575f80fd5b5f808335601e19843603018112615607575f80fd5b83018035915067ffffffffffffffff821115615621575f80fd5b6020019150600681901b36038213156130f8575f80fd5b5f60808236031215615648575f80fd5b6040516080810167ffffffffffffffff828210818311171561566c5761566c614d08565b816040528435915080821115615680575f80fd5b61568c36838701614f64565b8352602085013560208401526040850135604084015260608501359150808211156156b5575f80fd5b506156c236828601615132565b60608301525092915050565b5f602082840312156156de575f80fd5b813580151581146103bb575f80fd5b5f815180845260208085019450602084015f5b8381101561535557815180516001600160a01b031688528301518388015260409096019590820190600101615700565b5f6001600160a01b03808351168452602083015160a060208601528181511660a08601528160208201511660c08601526040810151915050606060e085015261577d610100850182614c4e565b90506040830151848203604086015261579682826156ed565b915050606083015184820360608601526157b082826156ed565b915050608083015160808501528091505092915050565b5f815180845260208085019450602084015f5b83811015615355578151875295820195908201906001016157da565b5f6001600160a01b03808716835260206080818501528651608080860152615822610100860182615730565b90508188015160a086015260408089015160c08701526060808a0151607f198885030160e08901528381518086528686019150868160051b87010187840193505f5b828110156158be57601f1988830301845284518a815116835289810151878b850152615892888501826157c7565b91890151848303858b01529190506158aa8183614c4e565b968b0196958b019593505050600101615864565b5080995050505050505050505083604083015282606083015295945050505050565b5f808335601e198436030181126158f5575f80fd5b83018035915067ffffffffffffffff82111561590f575f80fd5b6020019150368190038213156130f8575f80fd5b5f8235605e198336030181126155d4575f80fd5b5f6102b43683614e28565b5f60408284031215615952575f80fd5b6103bb8383614eb6565b6001600160a01b0384168152826020820152606060408201525f6152c16060830184615730565b6001600160a01b0385168152836020820152606060408201525f6159ab606083018486615215565b9695505050505050565b5f6103bb36848461500e565b818103818111156102b4576102b461553f565b828482375f8382015f815283518060208601835e5f910190815295945050505050565b5f6101206001600160a01b0387168352806020840152615a1981840187615730565b90508281036040840152615a2d8186615730565b9150508235606083015260208301356080830152604083013560a0830152606083013560c0830152608083013560e083015260a083013561010083015295945050505050565b602081525f6103bb6020830184615730565b5f60018201615a9657615a9661553f565b5060010190565b5f8282518085526020808601955060208260051b840101602086015f5b84811015615ae857601f19868403018952615ad68383516157c7565b98840198925090830190600101615aba565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e06060840152615b2e610100840182614c4e565b9050606084015160808401526080840151601f19808584030160a0860152615b568383615a9d565b925060a08601519150808584030160c0860152615b7383836157c7565b925060c08601519150808584030160e0860152506152c182826157c7565b5f82601f830112615ba0575f80fd5b81516020615bb0614f0e83614e93565b8083825260208201915060208460051b870101935086841115615bd1575f80fd5b602086015b84811015614f595780518352918301918301615bd6565b5f8060408385031215615bfe575f80fd5b825167ffffffffffffffff80821115615c15575f80fd5b818501915085601f830112615c28575f80fd5b81516020615c38614f0e83614e93565b82815260059290921b84018101918181019089841115615c56575f80fd5b948201945b83861015615c7457855182529482019490820190615c5b565b91880151919650909350505080821115615c8c575f80fd5b50615c9985828601615b91565b9150509250929050565b828152604060208201525f61052d60408301846157c7565b6001600160a01b0383168152604060208201525f61052d6040830184615a9d565b634e487b7160e01b5f52601260045260245ffd5b5f82615d0a57634e487b7160e01b5f52601260045260245ffd5b500490565b602081525f6103bb6020830184614c4e565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040810160048310615d6157634e487b7160e01b5f52602160045260245ffd5b8260208301529392505050565b8082018281125f8312801582168215821617156114ac576114ac61553f565b600181815b80851115615dc757815f1904821115615dad57615dad61553f565b80851615615dba57918102915b93841c9390800290615d92565b509250929050565b5f82615ddd575060016102b4565b81615de957505f6102b4565b8160018114615dff5760028114615e0957615e25565b60019150506102b4565b60ff841115615e1a57615e1a61553f565b50506001821b6102b4565b5060208310610133831016604e8410600b8410161715615e48575081810a6102b4565b615e528383615d8d565b805f1904821115615e6557615e6561553f565b029392505050565b5f6103bb8383615dcf565b5f8060408385031215615e89575f80fd5b825160048110615e97575f80fd5b602084015190925060ff81168114615ead575f80fd5b809150509250929050565b5f600160ff1b82016141975761419761553f56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00"; + hex"6080604052348015600e575f80fd5b5060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055616019806100405f395ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c8063613255ab11610093578063ac9650d811610063578063ac9650d81461022b578063d7e442ec1461024b578063d9d98ce41461025e578063fa50118214610271575f80fd5b8063613255ab146101ad57806369c72856146101c0578063709fb8a5146101e85780639235084d146101fb575f80fd5b80632fbc4ba0116100ce5780632fbc4ba01461015157806341d1514f146101665780635cffe9de14610187578063607461191461019a575f80fd5b806301ffc9a7146100f45780631f69cb751461011c5780632cb77e9f1461012f575b5f80fd5b610107610102366004614a14565b610284565b60405190151581526020015b60405180910390f35b61010761012a366004614a7c565b6102ba565b61010761013d366004614ae7565b5f9081526020819052604090205460011490565b61016461015f366004614b1d565b6103c2565b005b610179610174366004614b82565b610521565b604051908152602001610113565b610107610195366004614bc0565b610535565b6101646101a8366004614b1d565b610635565b6101796101bb366004614c57565b6107c8565b6101d36101ce366004614c88565b610830565b60408051928352602083019190915201610113565b6101076101f6366004614cba565b610fc9565b61020e610209366004614d04565b61130c565b604080519315158452602084019290925290820152606001610113565b61023e610239366004614d3b565b6113ce565b6040516101139190614da8565b610164610259366004614d3b565b6114b4565b61017961026c366004614e0a565b61150e565b61016461027f36600461527c565b6115a8565b5f6001600160e01b0319821663e414309160e01b14806102b457506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6102c3611a9a565b6102d06020850185614c57565b6001600160a01b0316336001600160a01b03161461031f576102f56020850185614c57565b6040516335252be360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b5f61033161032c86615336565b611ab5565b5f818152602081905260409020549091505f19016103a4575f818152602081905260408082209190915551600192507f09d18501db0080ca2d6cd7c17fa7255daff4b2d503ea93b76ff68b6752ea8e63906103919033908490899061548c565b60405180910390a16103a4818585611ae4565b506103bb60015f80516020615ff983398151915255565b9392505050565b6103ca611a9a565b3385856103d8838383611b1b565b6103e2865f611b4c565b610417576040516306dde9c360e41b81523360048201526001600160a01b038916602482015260448101889052606401610316565b5f80610424338b8a611b86565b604080513381526001600160a01b038e1660208201529081018c90526060810183905291935091507f7f9dfa19cf1cc2f806f2f860fbc9c056b601fb1afc0e9b843dfe5c63616268e69060800160405180910390a15f80610487338d8d8d611cbe565b909250905087156104fd5760408051600581526001600160a01b038e1660208201528082018d9052606081018490526080810183905260ff851660a082015260c081019091526104fd906104ee905b60408051600181526020810192909252818101905290565b6104f88a8c615550565b611dae565b5050505050505061051a60015f80516020615ff983398151915255565b5050505050565b5f61052d848484611f7c565b949350505050565b5f61054a6001600160a01b0386168786612106565b6040516323e30c8b60e01b81525f906001600160a01b038816906323e30c8b906105829033908a908a9087908b908b90600401615610565b6020604051808303815f875af115801561059e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c29190615654565b90507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9811461060757604051630b6c58a960e31b815260048101829052602401610316565b61062887306106165f8961567f565b6001600160a01b038a1692919061213b565b5060019695505050505050565b61063d611a9a565b33858561064b838383611b1b565b5f8080806106598a82611b4c565b61068d57604051623a3a4d60e21b81523360048201526001600160a01b038d166024820152604481018c9052606401610316565b5f610699338e8e611f7c565b90506106a58b82612177565b94506106b3338e8e88612193565b90935091505f6106c4338f8861220a565b80965081925050507f8045c25080b0868951141ed0a91720bcad09a8364a2b3109ee1fd49c1f0bc8b8338f8f8f8a86604051610736969594939291906001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b60405180910390a1505060408051600681526001600160a01b038e1660208201528082018d9052606081018490526080810183905260a081018c905260ff851660c0820152600160e08201908152610100820182905261012082019092529089156107a9576107a9816104f88c8e615550565b50505050505050505061051a60015f80516020615ff983398151915255565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa15801561080c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b49190615654565b5f8061083a611a9a565b6108476080840184615692565b90505f0361086857604051639c95219f60e01b815260040160405180910390fd5b61087061493c565b610878614968565b5f60405180606001604052808780608001906108949190615692565b5f8181106108a4576108a46156d8565b90506020028101906108b691906156ec565b6108c0908061570a565b6108ce90604081019061571e565b6108db60808b018b615692565b5f8181106108eb576108eb6156d8565b90506020028101906108fd91906156ec565b60200135818110610910576109106156d8565b6109269260206040909202019081019150614c57565b6001600160a01b031681526020016109416080890189615692565b5f818110610951576109516156d8565b905060200281019061096391906156ec565b61096d908061570a565b61097b90606081019061571e565b61098860808b018b615692565b5f818110610998576109986156d8565b90506020028101906109aa91906156ec565b604001358181106109bd576109bd6156d8565b6109d39260206040909202019081019150614c57565b6001600160a01b03168152602088810135910152905060605f6109f96080890189615692565b604080516001909201602002820181528501519093505f9250610a1d915082611b4c565b610a3a5760405163315f9e2360e21b815260040160405180910390fd5b5f5b610a4960808a018a615692565b905081108015610a6357506040840151610a63905f611b4c565b15610e7157610a7560808a018a615692565b82818110610a8557610a856156d8565b9050602002810190610a9791906156ec565b610aa090615764565b9550855f01519450835f01516001600160a01b03168560400151876020015181518110610acf57610acf6156d8565b60200260200101515f01516001600160a01b0316141580610b2a575083602001516001600160a01b03168560600151876040015181518110610b1357610b136156d8565b60200260200101515f01516001600160a01b031614155b15610b485760405163936bb5ad60e01b815260040160405180910390fd5b610b5b85876020015188604001516122e7565b5f610b6586611ab5565b5f81815260208190526040902054909150610bca578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a1610e68565b5f610c278789602001518a60400151338c606001515f67ffffffffffffffff811115610bf857610bf8614e34565b604051908082528060200260200182016040528015610c21578160200160208202803683370190505b50612359565b90505f610c458c604001358360600151611b4c90919063ffffffff16565b15610c9b578751604080513381526001600160a01b03909216602083015281018490527fe3151dc8cb7a54ffc4baabd28c1f241c94d510b5e5b502491ac3cad6c16316d5906060015b60405180910390a1610e5a565b6040820151610caa905f611b4c565b1580610cc257506060820151610cc0905f611b4c565b155b15610d0f578751604080513381526001600160a01b03909216602083015281018490527f500b713857325f9e6dcb52ae832eca9109d107ed1aae9cb4928b4c1e13f051aa90606001610c8e565b600190505f808d6060016020810190610d2891906157fa565b15610d6e576040808a015190850151610d4091612177565b6060850151909250610d52908361281e565b60408a0151909150610d64908361286b565b60408a0152610dd5565b5f610d8a8560400151866060015161281e90919063ffffffff16565b9050610da38a604001518261217790919063ffffffff16565b9150610dbc85606001518361289b90919063ffffffff16565b60408b0151909350610dce908361286b565b60408b0152505b610ddf8c826128cb565b9b50610deb8d836128cb565b9c50610df782856128fb565b610e0181856129bc565b7f194f1feb3b4d7076a2c272e774e792e0c48bb8c7aa1a9a3671c1cd6da9e6b4c1338c8484604051610e369493929190615922565b60405180910390a187516001018089526020028801849052610e5784612b68565b50505b8480610e635750805b945050505b50600101610a3c565b505f610e8360808a0160608b016157fa565b610e8d5786610e8f565b875b9050610e9c818a35612dab565b15610ec45760405163573b6f4160e01b81528935600482015260248101829052604401610316565b50610ed43384602001518961220a565b505f9050610ee560a08a018a615a0c565b9050118015610ef15750805b15610f635760208301518351339163691f9ed7918a8a610f1460a08f018f615a0c565b6040518763ffffffff1660e01b8152600401610f3596959493929190615610565b5f604051808303815f87803b158015610f4c575f80fd5b505af1158015610f5e573d5f803e3d5ffd5b505050505b610f7133845f015188611b86565b50505f5b8251811015610fa857610fa0838281518110610f9357610f936156d8565b6020026020010151612de5565b600101610f75565b505050505050610fc460015f80516020615ff983398151915255565b915091565b5f610fd2611a9a565b5f61102f61102a610fe38780615a4f565b610ff1906040810190615a0c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612eef92505050565b612f60565b90505f811161105157604051632cff108b60e21b815260040160405180910390fd5b6001811161107257604051633c8270bd60e21b815260040160405180910390fd5b61107f602086018661571e565b90505f036110a057604051636c44ef8f60e01b815260040160405180910390fd5b6110ad604086018661571e565b90505f036110ce5760405163540e5f0b60e01b815260040160405180910390fd5b6040805160a081019091523381525f90602081016110ec8880615a4f565b6110f590615a63565b815260200187806020019061110a919061571e565b808060200260200160405190810160405280939291908181526020015f905b828210156111555761114660408302860136819003810190615a6e565b81526020019060010190611129565b505050918352505060200161116d604089018961571e565b808060200260200160405190810160405280939291908181526020015f905b828210156111b8576111a960408302860136819003810190615a6e565b8152602001906001019061118c565b50505050508152602001876060013581525090505f6111d682611ab5565b5f818152602081905260409020549091501580156112f1575f828152602081905260409081902060019055835190517f87491344dfbcf91f6cbbc610cbbeedc85313d37a02df0c93527f7ea5f8db717f916112349185908790615a88565b60405180910390a15f61124a60a08a018a615a0c565b905011156112e65761129b61126260a08a018a615a0c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612f7a92505050565b82517fd46c2c56b35c8210e9e712ec3f02242d5fc90187c0ac8ed80cc33626846ec36990836112cd60a08c018c615a0c565b6040516112dd9493929190615aaf565b60405180910390a15b6112f1828888611ae4565b93505050506103bb60015f80516020615ff983398151915255565b5f80808061132661131d868061570a565b61032c90615336565b5f8181526020819052604090205490915060011461134d57505f92508291508190506113c7565b61137261135a868061570a565b61136390615336565b866020013587604001356122e7565b5f6113b0611380878061570a565b61138990615336565b60208801356040890135336113a160608c018c615692565b6113aa91615ae1565b5f610bf8565b905060018160400151826060015194509450945050505b9193909250565b604080515f8152602081019091526060908267ffffffffffffffff8111156113f8576113f8614e34565b60405190808252806020026020018201604052801561142b57816020015b60608152602001906001900390816114165790505b5091505f5b838110156114ac576114873086868481811061144e5761144e6156d8565b90506020028101906114609190615a0c565b8560405160200161147393929190615b00565b604051602081830303815290604052612fa5565b838281518110611499576114996156d8565b6020908102919091010152600101611430565b505092915050565b6114bc611a9a565b604080515f808252602082019092526114f4916114e9565b60608152602001906001900390816114d45790505b506104f88385615550565b61150a60015f80516020615ff983398151915255565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa158015611552573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115769190615654565b5f036115a057604051633c5bf76960e21b81526001600160a01b0384166004820152602401610316565b505f92915050565b6115b0611a9a565b835185516001600160a01b039182169116036115df57604051630a98f1f360e21b815260040160405180910390fd5b83604001518360400135815181106115f9576115f96156d8565b60200260200101515f01516001600160a01b03168560600151846020013581518110611627576116276156d8565b60200260200101515f01516001600160a01b03161415806116a0575060408501518051843590811061165b5761165b6156d8565b60200260200101515f01516001600160a01b03168460600151846060013581518110611689576116896156d8565b60200260200101515f01516001600160a01b031614155b156116be5760405163936bb5ad60e01b815260040160405180910390fd5b84606001518360200135815181106116d8576116d86156d8565b60200260200101515f01516001600160a01b03168560400151845f013581518110611705576117056156d8565b60200260200101515f01516001600160a01b03160361173757604051631cd2f1c760e21b815260040160405180910390fd5b5f61174186611ab5565b5f818152602081905260409020549091506117a7578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a150611a84565b5f6117b186611ab5565b5f81815260208190526040902054909150611818578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a15050611a84565b7f6fa7f4c28634b0a9d6831401c45ae468195fb63aed07308935c35374ff5d9e393388888860405161184d9493929190615b23565b60405180910390a1505083515f906118719087908635906020880135908686610bf8565b90505f6118a086866040013587606001358a5f0151885f67ffffffffffffffff811115610bf857610bf8614e34565b90505f6118ad8383613045565b90506118bc815f0151846128fb565b6118ca8160200151836128fb565b6118d88160400151846129bc565b6118e68160600151836129bc565b6118ef83612de5565b6118f882612de5565b606081015181515f9161190b919061286b565b90505f6119298360400151846020015161286b90919063ffffffff16565b9050611935825f612dab565b806119455750611945815f612dab565b1561196357604051630d86822160e01b815260040160405180910390fd5b611997338b606001518a6020013581518110611981576119816156d8565b60200260200101515f01518a6080013585611cbe565b50506119cd338a606001518a60600135815181106119b7576119b76156d8565b60200260200101515f01518a60a0013584611cbe565b5050604080513381528451602080830191909152850151818301529084015160608083019190915284015160808201527fd9fa84dd790c969daa5c33d8050dc06b4a9b59d5b42e2be5f5e8ae20447f618d925060a001905060405180910390a1611a3683612b68565b611a3f82612b68565b80516001600160e01b0316158015611a62575060208101516001600160e01b0316155b15611a80576040516321badf1f60e01b815260040160405180910390fd5b5050505b61051a60015f80516020615ff983398151915255565b611aa2613093565b60025f80516020615ff983398151915255565b5f81604051602001611ac79190615b9f565b604051602081830303815290604052805190602001209050919050565b604080516002815260208101859052338183015260608101909152611b1690611b0c906104d6565b6104f88385615550565b505050565b80611b16576040516305dbdfd960e41b81526001600160a01b03808516600483015283166024820152604401610316565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d611b7a848484846130c4565b12979650505050505050565b5f805f611b9285613198565b9050611b9e845f612dab565b15611bbc57604051632eaefac360e21b815260040160405180910390fd5b6001600160a01b038087165f90815260026020908152604080832093891683529290529081205490611bee868361286b565b90505f80611bfc8382611b4c565b15611c62575f611c0c84876131fe565b909350905080611c2257611c1f83615bb1565b92505b5f611c2d8a886131fe565b50905080611c3c85600161567f565b1015611c4a57809350600192505b611c5f6001600160a01b038c168d308761213b565b50505b5f611c6d838761322b565b50905081611c8457611c7f818561286b565b611c86565b845b6001600160a01b03808d165f908152600260209081526040808320938f1683529290522055509095509293505050505b935093915050565b5f80611cca8382612dab565b15611ceb5760405163793a8f5560e01b815260048101849052602401610316565b83611d0957611cfb86868561220a565b505f9250829150611da59050565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611d4382866128cb565b9050611d4f815f612dab565b15611d705760405163c5e12af560e01b815260048101829052602401610316565b6001600160a01b038089165f908152600160209081526040808320938b16835292815282822089835290522081905590925090505b94509492505050565b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b8651811015611f7257868181518110611e1557611e156156d8565b602002602001015193505f845f015160400151511115611f6a575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001611e8d8d8a6020015161326b565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401611eb89190615c21565b5f60405180830381865afa158015611ed2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611ef99190810190615d19565b9150505f81511115611f685784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490611f3a908a908590600401615dcf565b5f604051808303815f87803b158015611f51575f80fd5b505af1158015611f63573d5f803e3d5ffd5b505050505b505b600101611dfa565b5050505050505050565b5f8115611fb657506001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546103bb565b5f611fc08461354d565b6040516370a0823160e01b81526001600160a01b0387811660048301529192505f9161203891908716906370a0823190602401602060405180830381865afa15801561200e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120329190615654565b8361322b565b50604051636eb1769f60e11b81526001600160a01b0388811660048301523060248301529192505f916120b7919088169063dd62ed3e90604401602060405180830381865afa15801561208d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120b19190615654565b8461322b565b506001600160a01b038089165f908152600160209081526040808320938b168352928152828220828052905220549091506120fc906120f68484612177565b906128cb565b93505050506103bb565b6121138383836001613559565b611b1657604051635274afe760e01b81526001600160a01b0384166004820152602401610316565b6121498484848460016135bb565b61217157604051635274afe760e01b81526001600160a01b0385166004820152602401610316565b50505050565b5f6121828383612dab565b61218c57816103bb565b5090919050565b5f8061219f8382612dab565b156121c05760405163793a8f5560e01b815260048101849052602401610316565b836121d057611cfb868685611b86565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611d43828661286b565b5f805f61221685613198565b9050612222845f612dab565b1561224057604051632d1671a360e11b815260040160405180910390fd5b6001600160a01b038087165f9081526002602090815260408083209389168352929052908120546122729086906128cb565b90505f61227f82846131fe565b5090505f61228d828561322b565b50905061229a838261286b565b6001600160a01b03808b165f908152600260209081526040808320938d168352929052205581156122d9576122d96001600160a01b0389168a84612106565b509791965090945050505050565b826060015181815181106122fd576122fd6156d8565b60200260200101515f01516001600160a01b031683604001518381518110612327576123276156d8565b60200260200101515f01516001600160a01b031603611b1657604051631cd2f1c760e21b815260040160405180910390fd5b6123616149cf565b60408051600480825260a082019092526060915f9190816020015b606081526020019060019003908161237c5790505090506123d161239f8a611ab5565b8a51604080516003815260208101939093526001600160a01b0391821683820152908916606083015260808201905290565b8160018003815181106123e6576123e66156d8565b60200260200101819052505f61241b8a604001518a8151811061240b5761240b6156d8565b60200260200101515f015161354d565b90505f61246d8b5f01518c604001518c8151811061243b5761243b6156d8565b60200260200101515f01518d604001518d8151811061245c5761245c6156d8565b602002602001015160200151611f7c565b90506124fc8b604001518b81518110612488576124886156d8565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d604001518d815181106124ba576124ba6156d8565b602002602001015160200151845f801b60408051600581526020810196909652858101949094526060850192909252608084015260a083015260c08201905290565b83600160030381518110612512576125126156d8565b602002602001018190525050505f6125398a60600151898151811061240b5761240b6156d8565b90505f61257a8b5f01518c606001518b81518110612559576125596156d8565b60200260200101515f01518d606001518c8151811061245c5761245c6156d8565b90506125c78b606001518a81518110612595576125956156d8565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d606001518c815181106124ba576124ba6156d8565b836001600403815181106125dd576125dd6156d8565b602002602001018190525050506125f4818661326b565b9150505f885f01516001600160a01b031690505f808a602001515f01516001600160a01b031663d04dfe236040518060e001604052808e60200151602001516001600160a01b0316815260200161265487305f9182526020526040902090565b81526020018e602001516040015181526020015f81526020018781526020015f67ffffffffffffffff81111561268c5761268c614e34565b6040519080825280602002602001820160405280156126b5578160200160208202803683370190505b508152602001898152506040518263ffffffff1660e01b81526004016126db9190615c21565b5f60405180830381865afa1580156126f5573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261271c9190810190615d19565b91509150600282511015612748578151604051630fbb8e5560e21b815260040161031691815260200190565b60208201516040830151855161279c908790600490811061276b5761276b6156d8565b6020026020010151600381518110612785576127856156d8565b60200260200101518261217790919063ffffffff16565b60408051600281526020810183905280820185905260608101909152909150866002815181106127ce576127ce6156d8565b60200260200101819052506040518060e001604052808e81526020018c81526020018281526020018381526020018781526020018681526020018481525096505050505050509695505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613628565b915091505f61285d8383613747565b9a9950505050505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613794565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e868686866137be565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613cfb565b818160800151600481518110612913576129136156d8565b602002602001015160048151811061292d5761292d6156d8565b602002602001018181525050612171815f01515f0151826080015160048151811061295a5761295a6156d8565b60200260200101515f81518110612973576129736156d8565b60200260200101515f1c8360800151600481518110612994576129946156d8565b60200260200101516002815181106129ae576129ae6156d8565b602002602001015185612193565b8181608001516003815181106129d4576129d46156d8565b60200260200101516004815181106129ee576129ee6156d8565b6020908102919091010152805151608082015180515f91906003908110612a1757612a176156d8565b60200260200101515f81518110612a3057612a306156d8565b60200260200101515f1c90505f8360800151600381518110612a5457612a546156d8565b6020026020010151600281518110612a6e57612a6e6156d8565b602002602001015190505f801b8103612b1557612a8b855f612dab565b15612aac5760405163793a8f5560e01b815260048101869052602401610316565b6001600160a01b038084165f908152600160209081526040808320938616835292815282822084835290522054612ae390866128cb565b6001600160a01b038085165f908152600160209081526040808320938716835292815282822085835290522055612b24565b612b2183838388611cbe565b50505b7f4cb6e22a3e7e651d7cf0376cff48f20f5007a54147777865be7f5f6c38c50f4a338560800151604051612b59929190615de7565b60405180910390a15050505050565b60c08101515115612be2578051602090810151015160a082015160c083015160405163012c676d60e21b81526001600160a01b03909316926304b19db492612bb4929091600401615dcf565b5f604051808303815f87803b158015612bcb575f80fd5b505af1158015612bdd573d5f803e3d5ffd5b505050505b5f815f0151602001515f01516001600160a01b031663d04dfe236040518060e00160405280855f015160200151602001516001600160a01b03168152602001612c388660a00151305f9182526020526040902090565b8152602001855f01516020015160400151815260200160018152602001856080015181526020015f67ffffffffffffffff811115612c7857612c78614e34565b604051908082528060200260200182016040528015612ca1578160200160208202803683370190505b5081526020015f604051908082528060200260200182016040528015612cd1578160200160208202803683370190505b508152506040518263ffffffff1660e01b8152600401612cf19190615c21565b5f60405180830381865afa158015612d0b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612d329190810190615d19565b9150505f8151111561150a578151602090810151015160a083015160405163012c676d60e21b81526001600160a01b03909216916304b19db491612d7a918590600401615dcf565b5f604051808303815f87803b158015612d91575f80fd5b505af1158015612da3573d5f803e3d5ffd5b505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d612dd9848484846130c4565b13979650505050505050565b5f8160800151600381518110612dfd57612dfd6156d8565b6020026020010151600281518110612e1757612e176156d8565b602002602001015190505f801b810361150a57815151608083015180515f91906003908110612e4857612e486156d8565b60200260200101515f81518110612e6157612e616156d8565b6020908102919091018101516001600160a01b038481165f9081526001845260408082209284168252918452818120878252909352909120549091506001600160e01b0381161561051a576001600160a01b038084165f9081526001602090815260408083209386168352928152828220878352905290812055612ee683838361220a565b50505050505050565b6060604082511015612f0e57505060408051602081019091525f815290565b5f60208301519050602060408451612f269190615aed565b612f309190615e1c565b811115612f4c57505060408051602081019091525f8152919050565b600181016020026020840101915050919050565b5f81515f03612f7057505f919050565b50602001515f1a90565b612f8381613df9565b612fa25780604051630c89984b60e31b81526004016103169190615e3b565b50565b60605f612fb28484613e27565b9050808015612fd357505f3d1180612fd357505f846001600160a01b03163b115b15612fe857612fe0613e3a565b9150506102b4565b801561301257604051639996b31560e01b81526001600160a01b0385166004820152602401610316565b3d1561302557613020613e53565b61303e565b60405163d6bda27560e01b815260040160405180910390fd5b5092915050565b604080516080810182525f8082526020820181905291810182905260608101919091526130728383613e5e565b825260408201526130838284613e5e565b6020830152606082015292915050565b5f80516020615ff9833981519152546002036130c257604051633ee5aeb560e01b815260040160405180910390fd5b565b5f80851584151781871282861218178584141780156130e95786859250925050611da5565b505f858413156130fd575092949193919260015b8386035f8112604c8213178015613130578215613122575f8994509450505050611da5565b885f94509450505050611da5565b600a82900a8981028a82828161314857613148615e08565b0514613174578415613164575f8b965096505050505050611da5565b8a5f965096505050505050611da5565b8415613189578896509450611da59350505050565b9550879450611da59350505050565b5f805f6131a484613ec7565b909250905060018260038111156131bd576131bd615e4d565b141580156131dc57505f8260038111156131d9576131d9615e4d565b14155b156103bb57838260405163ee07877f60e01b8152600401610316929190615e61565b5f806001600160e01b038416601b0b60e085901d61321d828287613f54565b9350935050505b9250929050565b5f805f805f61323a87876140ba565b9250925092505f8061324c85856140fd565b915091508183801561325b5750815b9650965050505050509250929050565b60605f825167ffffffffffffffff81111561328857613288614e34565b6040519080825280602002602001820160405280156132b1578160200160208202803683370190505b5090505f808451116132c3575f6132c9565b83516001015b85516001010190505f8167ffffffffffffffff8111156132eb576132eb614e34565b60405190808252806020026020018201604052801561331e57816020015b60608152602001906001900390816133095790505b5090505f613342604080516002815233602082015230818301526060810190915290565b828281518110613354576133546156d8565b60200260200101819052505f5b87518110156133b1578180600101925050878181518110613384576133846156d8565b602002602001015183838151811061339e5761339e6156d8565b6020908102919091010152600101613361565b50855115613543578080600101915050838282815181106133d4576133d46156d8565b60200260200101819052505f5b8651811015613541576134908782815181106133ff576133ff6156d8565b60200260200101515f015161346d61343b8a8581518110613422576134226156d8565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b89848151811061347f5761347f6156d8565b6020026020010151604001516141d5565b6134b057604051630a57f30960e31b815260048101829052602401610316565b8681815181106134c2576134c26156d8565b60200260200101515f01516001600160a01b03165f1b8582815181106134ea576134ea6156d8565b6020026020010181815250508180600101925050868181518110613510576135106156d8565b60200260200101516020015183838151811061352e5761352e6156d8565b60209081029190910101526001016133e1565b505b5095945050505050565b5f805f6131a484614245565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f511483166135af5783831516156135a3573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b6040516323b872dd60e01b5f8181526001600160a01b038781166004528616602452604485905291602083606481808c5af1925060015f5114831661361757838315161561360b573d5f823e3d81fd5b5f883b113d1516831692505b604052505f60605295945050505050565b5f8085158415178015613640575f92505f915061373d565b61364a8487615e9a565b91505f613656886142a4565b90505f613662876142a4565b90505f61366f83836142d2565b5090505f6f0785ee10d5da46d900f436a0000000008211156136a4576f0785ee10d5da46d900f436a000000000820491506025015b670de0b6b3a76400008211156136c557670de0b6b3a7640000820491506012015b633b9aca008211156136de57633b9aca00820491506009015b6127108211156136f357612710820491506004015b811561370757600a820491506001016136f3565b6137118187615e9a565b95506137338b8a61372d878761372887600a615f99565b6142ee565b896143ba565b9097509550505050505b5094509492505050565b5f805f61375485856140fd565b9150915080158015613764575081155b1561378c57604051638eba4d0760e01b81526004810186905260248101859052604401610316565b509392505050565b5f806137a0848461445a565b90945092506137b186868686613cfb565b9150915094509492505050565b5f80835f036137ea57604051637a97930f60e01b81526004810187905260248101869052604401610316565b855f036137fb57505f905080611da5565b5f805f806138098a8a6144af565b919b509950915061381a88886144af565b919950975090505f61382b8b6142a4565b90505f6138378a6142a4565b90507f161bcca7119915b50764b4abe86529797775a5f1719510000000000000000000604c81831015613bfc57841561388e57507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b9050604b613bd4565b6f4b3b4ca85a86c47a098a2240000000008310156139ba57678ac7230489e8000083101561391e576402540be4008310156138ec57620186a08310156138dc5750620186a090506005613b95565b506402540be4009050600a613b95565b655af3107a400083101561390b5750655af3107a40009050600e613b95565b50678ac7230489e8000090506013613b95565b6b204fce5e3e250261100000008310156139705769152d02c7e14af6800000831015613959575069152d02c7e14af680000090506017613b95565b506b204fce5e3e250261100000009050601c613b95565b6d314dc6448d9338c15b0a0000000083101561399f57506d314dc6448d9338c15b0a0000000090506021613b95565b506f4b3b4ca85a86c47a098a22400000000090506026613b95565b780197d4df19d605767337e9f14d3eec8920e400000000000000831015613ab25773af298d050e4395d69670b12b7f41000000000000831015613a4d577172cb5bd86321e38cb6ce6682e80000000000831015613a2e57507172cb5bd86321e38cb6ce6682e800000000009050602b613b95565b5073af298d050e4395d69670b12b7f4100000000000090506030613b95565b76010b46c6cdd6e3e0828f4db456ff0c8ea0000000000000831015613a8e575076010b46c6cdd6e3e0828f4db456ff0c8ea000000000000090506035613b95565b50780197d4df19d605767337e9f14d3eec8920e4000000000000009050603a613b95565b7c03b58e88c75313ec9d329eaaa18fb92f75215b17100000000000000000831015613b48577a026e4d30eccc3215dd8f3157d27e23acbdcfe68000000000000000831015613b2057507a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000009050603f613b95565b507c03b58e88c75313ec9d329eaaa18fb92f75215b1710000000000000000090506044613b95565b7e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000831015613b9557507e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000905060495b818311613baa57600a820491505f1901613b95565b815f03613bd4576040516305e51ecb60e01b8152600481018d9052602481018c9052604401610316565b85613bfc576040516305e51ecb60e01b8152600481018f9052602481018e9052604401610316565b80600160ff1b018d12613c1357808d039c50613c51565b600160ff1b9c90038c015f811315613c5157806001600160ff1b03038b13613c3e57998a0199613c51565b5f80995099505050505050505050611da5565b5f808e128015613c6057505f8c135b15613c8157600160ff1b8e01808d13613c79575f613c7d565b808d035b9150505b8b818f01039750613c9e8f8e613c988887896142ee565b8b6143ba565b90995097505f811315613ce857604c811315613cc8575f809a509a50505050505050505050611da5565b80600a0a8981613cda57613cda615e08565b059850885f03613ce8575f97505b50969850949650611da595505050505050565b5f8085158415178015613d2757865f03613d1b5784849250925050611da5565b86869250925050611da5565b613d318787614709565b9097509550613d408585614709565b909550935085841315613d54579395929492935b838603604c811115613d6d578787935093505050611da5565b80600a0a8681613d7f57613d7f615e08565b0595505086850180881860ff90811c151589881890911c15168015613de857876001600160ff1b0303613dcf5760405163d556b11160e01b8152600481018a905260248101899052604401610316565b600a968790059690980586019760019790970196613dec565b8198505b5096979596505050505050565b5f600882511015613e0b57505f919050565b506008015167ffffffffffffffff1667ff0a89c674ee78741490565b5f805f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f80613e7b8460600151856040015161281e90919063ffffffff16565b915083604001519050613e9b836040015183611b4c90919063ffffffff16565b156132245782604001519150613ebe84606001518361289b90919063ffffffff16565b90509250929050565b5f80613ed1614752565b60405163b7bad1b160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb93899063b7bad1b19060240160408051808303815f875af1158015613f27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f4b9190615fa4565b91509150915091565b5f805f851215613f8157604051634a7d166b60e01b81526004810186905260248101859052604401610316565b845f03613f9357505f90506001611cb6565b8460ff8416850185811215613fc55760405163d556b11160e01b81526004810188905260248101879052604401610316565b5f805f83121561401157604c19831215613fe8575f809550955050505050611cb6565b825f03600a0a9150818481613fff57613fff615e08565b0495505084029091149150611cb69050565b5f8313156140aa57604d83131561404e5760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b82600a0a9150815f198161406457614064615e08565b048411156140985760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b5091909102925060019150611cb69050565b8360019550955050505050611cb6565b5f808060ff841681036001600160ff1b038611156140ec57600a860460018201600a88065f14935093509350506140f6565b8593509150600190505b9250925092565b5f601b83900b8314838382614161577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e100000000000000000086051561414157620186a0860595506005850194505b8586601b0b1461415c57600a86059550846001019450614141565b614177565b855f0361417757505f9250600191506132249050565b848560030b146141ba575f85121561419757505f92508291506132249050565b60405163d556b11160e01b81526004810183905260248101829052604401610316565b50506001600160e01b03841660e084901b1791509250929050565b5f836001600160a01b03163b5f03614233575f806141f385856147dd565b5090925090505f81600381111561420c5761420c615e4d565b14801561422a5750856001600160a01b0316826001600160a01b0316145b925050506103bb565b61423e848484614823565b90506103bb565b5f8061424f614752565b604051630782d7e160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb938990630782d7e1906024016040805180830381865afa158015613f27573d5f803e3d5ffd5b5f808212156142c957600160ff1b82036142c35750600160ff1b919050565b505f0390565b5090565b919050565b5f805f1983850993909202808410938190039390930393915050565b5f805f6142fb86866142d2565b91509150815f0361431f5783818161431557614315615e08565b04925050506103bb565b8382106143505760405163362ced0960e11b8152600481018790526024810186905260448101859052606401610316565b5f84868809600186198101871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103025f82900382900490920185841190960395909502919093039390930492909217029150509392505050565b5f805f8587181215614436576001600160ff1b03841115614423576143e76001600160ff1b03600161567f565b84036143fb5750600160ff1b905081611da5565b614406600a85615e1c565b61440f90615fe4565b61441a846001615e9a565b91509150611da5565b61442c84615fe4565b8391509150611da5565b6001600160ff1b038411156144505761440f600a85615e1c565b5082905081611da5565b5f80600160ff1b84036144a5576001600160ff1b0383036144985760405163d556b11160e01b81526004810185905260248101849052604401610316565b600a840593508260010192505b50505f9190910391565b5f805f845f036144c757505f915081905060016140f6565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85055f036146b4576f4b3b4ca85a86c47a098a224000000000850515801561452957507f80000000000000000000000000000000000000000000000000000000000000268412155b1561454a576f4b3b4ca85a86c47a098a224000000000850294506026840393505b7728c87cb5c89a2571ebfdcb54864ada834a00000000000000850515801561459257507f80000000000000000000000000000000000000000000000000000000000000138412155b156145ab57678ac7230489e80000850294506013840393505b7b097edd871cfda3a5697758bf0e3cbb5ac5741c64000000000000000085051580156145f757507f800000000000000000000000000000000000000000000000000000000000000a8412155b1561460d576402540be40085029450600a840393505b7e3899162693736ac531a5a58f1fbb4b746504382ca7e4000000000000000000850515801561465c57507f80000000000000000000000000000000000000000000000000000000000000028412155b156146725760648502945060028403935061460d565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85051580156146a257506001600160ff1b018412155b156146b457600a850294506001840393505b600a808602908105861480156146d157506001600160ff1b018512155b156146e0578095506001850394505b50939492935050507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b8305151590565b5f805f805f61471887876144af565b92509250925080614746576040516305e51ecb60e01b81526004810188905260248101879052604401610316565b50909590945092505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b15806147a9575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b156130c2576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610316565b5f805f8351604103614814576020840151604085015160608601515f1a61480688828585614874565b9550955095505050506140f6565b505081515f91506002906140f6565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156148ad57505f91506003905082614932565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156148fe573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661492957505f925060019150829050614932565b92505f91508190505b9450945094915050565b604051806080016040528061494f614968565b81526020015f81526020015f8152602001606081525090565b6040518060a001604052805f6001600160a01b031681526020016149b660405180606001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b8152606060208201819052604082018190525f91015290565b6040518060e001604052806149e2614968565b81526020015f81526020015f80191681526020015f8019168152602001606081526020015f8152602001606081525090565b5f60208284031215614a24575f80fd5b81356001600160e01b0319811681146103bb575f80fd5b5f8083601f840112614a4b575f80fd5b50813567ffffffffffffffff811115614a62575f80fd5b6020830191508360208260051b8501011115613224575f80fd5b5f805f60408486031215614a8e575f80fd5b833567ffffffffffffffff80821115614aa5575f80fd5b9085019060a08288031215614ab8575f80fd5b90935060208501359080821115614acd575f80fd5b50614ada86828701614a3b565b9497909650939450505050565b5f60208284031215614af7575f80fd5b5035919050565b6001600160a01b0381168114612fa2575f80fd5b80356142cd81614afe565b5f805f805f60808688031215614b31575f80fd5b8535614b3c81614afe565b94506020860135935060408601359250606086013567ffffffffffffffff811115614b65575f80fd5b614b7188828901614a3b565b969995985093965092949392505050565b5f805f60608486031215614b94575f80fd5b8335614b9f81614afe565b92506020840135614baf81614afe565b929592945050506040919091013590565b5f805f805f60808688031215614bd4575f80fd5b8535614bdf81614afe565b94506020860135614bef81614afe565b935060408601359250606086013567ffffffffffffffff80821115614c12575f80fd5b818801915088601f830112614c25575f80fd5b813581811115614c33575f80fd5b896020828501011115614c44575f80fd5b9699959850939650602001949392505050565b5f60208284031215614c67575f80fd5b81356103bb81614afe565b5f60c08284031215614c82575f80fd5b50919050565b5f60208284031215614c98575f80fd5b813567ffffffffffffffff811115614cae575f80fd5b61052d84828501614c72565b5f805f60408486031215614ccc575f80fd5b833567ffffffffffffffff80821115614ce3575f80fd5b614cef87838801614c72565b94506020860135915080821115614acd575f80fd5b5f60208284031215614d14575f80fd5b813567ffffffffffffffff811115614d2a575f80fd5b8201608081850312156103bb575f80fd5b5f8060208385031215614d4c575f80fd5b823567ffffffffffffffff811115614d62575f80fd5b614d6e85828601614a3b565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614dfd57603f19888603018452614deb858351614d7a565b94509285019290850190600101614dcf565b5092979650505050505050565b5f8060408385031215614e1b575f80fd5b8235614e2681614afe565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b60405290565b6040805190810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b60405160a0810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b604051601f8201601f1916810167ffffffffffffffff81118282101715614ee057614ee0614e34565b604052919050565b5f82601f830112614ef7575f80fd5b813567ffffffffffffffff811115614f1157614f11614e34565b614f24601f8201601f1916602001614eb7565b818152846020838601011115614f38575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608284031215614f64575f80fd5b614f6c614e48565b90508135614f7981614afe565b81526020820135614f8981614afe565b6020820152604082013567ffffffffffffffff811115614fa7575f80fd5b614fb384828501614ee8565b60408301525092915050565b5f67ffffffffffffffff821115614fd857614fd8614e34565b5060051b60200190565b5f60408284031215614ff2575f80fd5b614ffa614e71565b9050813561500781614afe565b808252506020820135602082015292915050565b5f82601f83011261502a575f80fd5b8135602061503f61503a83614fbf565b614eb7565b8083825260208201915060208460061b870101935086841115615060575f80fd5b602086015b84811015615085576150778882614fe2565b835291830191604001615065565b509695505050505050565b5f60a082840312156150a0575f80fd5b6150a8614e94565b90506150b382614b12565b8152602082013567ffffffffffffffff808211156150cf575f80fd5b6150db85838601614f54565b602084015260408401359150808211156150f3575f80fd5b6150ff8583860161501b565b60408401526060840135915080821115615117575f80fd5b506151248482850161501b565b6060830152506080820135608082015292915050565b5f61514761503a84614fbf565b8381529050602080820190600585811b850187811115615165575f80fd5b855b8181101561525257803567ffffffffffffffff80821115615186575f80fd5b908801906060828c031215615199575f80fd5b6151a1614e48565b82356151ac81614afe565b815282870135828111156151be575f80fd5b8301601f81018d136151ce575f80fd5b80356151dc61503a82614fbf565b81815290881b8201890190898101908f8311156151f7575f80fd5b928a01925b828410156152155783358252928a0192908a01906151fc565b848b0152506040915050838101358381111561522f575f80fd5b61523b8e828701614ee8565b918301919091525087525050938301938301615167565b50505050509392505050565b5f82601f83011261526d575f80fd5b6103bb8383356020850161513a565b5f805f805f6101408688031215615291575f80fd5b853567ffffffffffffffff808211156152a8575f80fd5b6152b489838a01615090565b965060208801359150808211156152c9575f80fd5b6152d589838a01615090565b95506152e48960408a01614c72565b94506101008801359150808211156152fa575f80fd5b61530689838a0161525e565b935061012088013591508082111561531c575f80fd5b506153298882890161525e565b9150509295509295909350565b5f6102b43683615090565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f813561537581614afe565b6001600160a01b03908116845260208301359061539182614afe565b166020840152604082013536839003601e190181126153ae575f80fd5b820160208101903567ffffffffffffffff8111156153ca575f80fd5b8036038213156153d8575f80fd5b606060408601526153ed606086018284615341565b95945050505050565b5f808335601e1984360301811261540b575f80fd5b830160208101925035905067ffffffffffffffff81111561542a575f80fd5b8060061b3603821315613224575f80fd5b8183525f60208085019450825f5b8581101561548157813561545c81614afe565b6001600160a01b03168752818301358388015260409687019690910190600101615449565b509495945050505050565b5f6001600160a01b0380861683528460208401526060604084015283356154b281614afe565b166060830152602083013536849003605e190181126154cf575f80fd5b60a060808401526154e66101008401858301615369565b90506154f560408501856153f6565b605f19808685030160a087015261550d84838561543b565b935061551c60608801886153f6565b93509150808685030160c08701525061553683838361543b565b92505050608084013560e084015280915050949350505050565b5f61555d61503a84614fbf565b80848252602080830192508560051b85013681111561557a575f80fd5b855b8181101561560457803567ffffffffffffffff8082111561559b575f80fd5b8189019150604082360312156155af575f80fd5b6155b7614e71565b8235828111156155c5575f80fd5b6155d136828601614f54565b82525085830135828111156155e4575f80fd5b6155f03682860161525e565b82880152508752505093820193820161557c565b50919695505050505050565b5f6001600160a01b03808916835280881660208401525085604083015284606083015260a0608083015261564860a083018486615341565b98975050505050505050565b5f60208284031215615664575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102b4576102b461566b565b5f808335601e198436030181126156a7575f80fd5b83018035915067ffffffffffffffff8211156156c1575f80fd5b6020019150600581901b3603821315613224575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112615700575f80fd5b9190910192915050565b5f8235609e19833603018112615700575f80fd5b5f808335601e19843603018112615733575f80fd5b83018035915067ffffffffffffffff82111561574d575f80fd5b6020019150600681901b3603821315613224575f80fd5b5f60808236031215615774575f80fd5b6040516080810167ffffffffffffffff828210818311171561579857615798614e34565b8160405284359150808211156157ac575f80fd5b6157b836838701615090565b8352602085013560208401526040850135604084015260608501359150808211156157e1575f80fd5b506157ee3682860161525e565b60608301525092915050565b5f6020828403121561580a575f80fd5b813580151581146103bb575f80fd5b5f815180845260208085019450602084015f5b8381101561548157815180516001600160a01b03168852830151838801526040909601959082019060010161582c565b5f6001600160a01b03808351168452602083015160a060208601528181511660a08601528160208201511660c08601526040810151915050606060e08501526158a9610100850182614d7a565b9050604083015184820360408601526158c28282615819565b915050606083015184820360608601526158dc8282615819565b915050608083015160808501528091505092915050565b5f815180845260208085019450602084015f5b8381101561548157815187529582019590820190600101615906565b5f6001600160a01b0380871683526020608081850152865160808086015261594e61010086018261585c565b90508188015160a086015260408089015160c08701526060808a0151607f198885030160e08901528381518086528686019150868160051b87010187840193505f5b828110156159ea57601f1988830301845284518a815116835289810151878b8501526159be888501826158f3565b91890151848303858b01529190506159d68183614d7a565b968b0196958b019593505050600101615990565b5080995050505050505050505083604083015282606083015295945050505050565b5f808335601e19843603018112615a21575f80fd5b83018035915067ffffffffffffffff821115615a3b575f80fd5b602001915036819003821315613224575f80fd5b5f8235605e19833603018112615700575f80fd5b5f6102b43683614f54565b5f60408284031215615a7e575f80fd5b6103bb8383614fe2565b6001600160a01b0384168152826020820152606060408201525f6153ed606083018461585c565b6001600160a01b0385168152836020820152606060408201525f615ad7606083018486615341565b9695505050505050565b5f6103bb36848461513a565b818103818111156102b4576102b461566b565b828482375f8382015f815283518060208601835e5f910190815295945050505050565b5f6101206001600160a01b0387168352806020840152615b458184018761585c565b90508281036040840152615b59818661585c565b9150508235606083015260208301356080830152604083013560a0830152606083013560c0830152608083013560e083015260a083013561010083015295945050505050565b602081525f6103bb602083018461585c565b5f60018201615bc257615bc261566b565b5060010190565b5f8282518085526020808601955060208260051b840101602086015f5b84811015615c1457601f19868403018952615c028383516158f3565b98840198925090830190600101615be6565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e06060840152615c5a610100840182614d7a565b9050606084015160808401526080840151601f19808584030160a0860152615c828383615bc9565b925060a08601519150808584030160c0860152615c9f83836158f3565b925060c08601519150808584030160e0860152506153ed82826158f3565b5f82601f830112615ccc575f80fd5b81516020615cdc61503a83614fbf565b8083825260208201915060208460051b870101935086841115615cfd575f80fd5b602086015b848110156150855780518352918301918301615d02565b5f8060408385031215615d2a575f80fd5b825167ffffffffffffffff80821115615d41575f80fd5b818501915085601f830112615d54575f80fd5b81516020615d6461503a83614fbf565b82815260059290921b84018101918181019089841115615d82575f80fd5b948201945b83861015615da057855182529482019490820190615d87565b91880151919650909350505080821115615db8575f80fd5b50615dc585828601615cbd565b9150509250929050565b828152604060208201525f61052d60408301846158f3565b6001600160a01b0383168152604060208201525f61052d6040830184615bc9565b634e487b7160e01b5f52601260045260245ffd5b5f82615e3657634e487b7160e01b5f52601260045260245ffd5b500490565b602081525f6103bb6020830184614d7a565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040810160048310615e8d57634e487b7160e01b5f52602160045260245ffd5b8260208301529392505050565b8082018281125f8312801582168215821617156114ac576114ac61566b565b600181815b80851115615ef357815f1904821115615ed957615ed961566b565b80851615615ee657918102915b93841c9390800290615ebe565b509250929050565b5f82615f09575060016102b4565b81615f1557505f6102b4565b8160018114615f2b5760028114615f3557615f51565b60019150506102b4565b60ff841115615f4657615f4661566b565b50506001821b6102b4565b5060208310610133831016604e8410600b8410161715615f74575081810a6102b4565b615f7e8383615eb9565b805f1904821115615f9157615f9161566b565b029392505050565b5f6103bb8383615efb565b5f8060408385031215615fb5575f80fd5b825160048110615fc3575f80fd5b602084015190925060ff81168114615fd9575f80fd5b809150509250929050565b5f600160ff1b82016142c3576142c361566b56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00"; /// @dev The runtime bytecode of the contract. bytes constant RUNTIME_CODE = - hex"608060405234801561000f575f80fd5b50600436106100f0575f3560e01c8063613255ab11610093578063ac9650d811610063578063ac9650d81461022b578063d7e442ec1461024b578063d9d98ce41461025e578063fa50118214610271575f80fd5b8063613255ab146101ad57806369c72856146101c0578063709fb8a5146101e85780639235084d146101fb575f80fd5b80632fbc4ba0116100ce5780632fbc4ba01461015157806341d1514f146101665780635cffe9de14610187578063607461191461019a575f80fd5b806301ffc9a7146100f45780631f69cb751461011c5780632cb77e9f1461012f575b5f80fd5b6101076101023660046148e8565b610284565b60405190151581526020015b60405180910390f35b61010761012a366004614950565b6102ba565b61010761013d3660046149bb565b5f9081526020819052604090205460011490565b61016461015f3660046149f1565b6103c2565b005b610179610174366004614a56565b610521565b604051908152602001610113565b610107610195366004614a94565b610535565b6101646101a83660046149f1565b610635565b6101796101bb366004614b2b565b6107c8565b6101d36101ce366004614b5c565b610830565b60408051928352602083019190915201610113565b6101076101f6366004614b8e565b610fc9565b61020e610209366004614bd8565b61130c565b604080519315158452602084019290925290820152606001610113565b61023e610239366004614c0f565b6113ce565b6040516101139190614c7c565b610164610259366004614c0f565b6114b4565b61017961026c366004614cde565b61150e565b61016461027f366004615150565b6115a8565b5f6001600160e01b0319821663e414309160e01b14806102b457506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6102c3611a9a565b6102d06020850185614b2b565b6001600160a01b0316336001600160a01b03161461031f576102f56020850185614b2b565b6040516335252be360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b5f61033161032c8661520a565b611ab5565b5f818152602081905260409020549091505f19016103a4575f818152602081905260408082209190915551600192507f09d18501db0080ca2d6cd7c17fa7255daff4b2d503ea93b76ff68b6752ea8e639061039190339084908990615360565b60405180910390a16103a4818585611ae4565b506103bb60015f80516020615ecd83398151915255565b9392505050565b6103ca611a9a565b3385856103d8838383611b1b565b6103e2865f611b4c565b610417576040516306dde9c360e41b81523360048201526001600160a01b038916602482015260448101889052606401610316565b5f80610424338b8a611b86565b604080513381526001600160a01b038e1660208201529081018c90526060810183905291935091507f7f9dfa19cf1cc2f806f2f860fbc9c056b601fb1afc0e9b843dfe5c63616268e69060800160405180910390a15f80610487338d8d8d611c06565b909250905087156104fd5760408051600581526001600160a01b038e1660208201528082018d9052606081018490526080810183905260ff851660a082015260c081019091526104fd906104ee905b60408051600181526020810192909252818101905290565b6104f88a8c615424565b611cf6565b5050505050505061051a60015f80516020615ecd83398151915255565b5050505050565b5f61052d848484611ec4565b949350505050565b5f61054a6001600160a01b038616878661204e565b6040516323e30c8b60e01b81525f906001600160a01b038816906323e30c8b906105829033908a908a9087908b908b906004016154e4565b6020604051808303815f875af115801561059e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c29190615528565b90507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9811461060757604051630b6c58a960e31b815260048101829052602401610316565b61062887306106165f89615553565b6001600160a01b038a16929190612083565b5060019695505050505050565b61063d611a9a565b33858561064b838383611b1b565b5f8080806106598a82611b4c565b61068d57604051623a3a4d60e21b81523360048201526001600160a01b038d166024820152604481018c9052606401610316565b5f610699338e8e611ec4565b90506106a58b826120bf565b94506106b3338e8e886120db565b90935091505f6106c4338f88612152565b80965081925050507f8045c25080b0868951141ed0a91720bcad09a8364a2b3109ee1fd49c1f0bc8b8338f8f8f8a86604051610736969594939291906001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b60405180910390a1505060408051600681526001600160a01b038e1660208201528082018d9052606081018490526080810183905260a081018c905260ff851660c0820152600160e08201908152610100820182905261012082019092529089156107a9576107a9816104f88c8e615424565b50505050505050505061051a60015f80516020615ecd83398151915255565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa15801561080c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b49190615528565b5f8061083a611a9a565b6108476080840184615566565b90505f0361086857604051639c95219f60e01b815260040160405180910390fd5b610870614810565b61087861483c565b5f60405180606001604052808780608001906108949190615566565b5f8181106108a4576108a46155ac565b90506020028101906108b691906155c0565b6108c090806155de565b6108ce9060408101906155f2565b6108db60808b018b615566565b5f8181106108eb576108eb6155ac565b90506020028101906108fd91906155c0565b60200135818110610910576109106155ac565b6109269260206040909202019081019150614b2b565b6001600160a01b031681526020016109416080890189615566565b5f818110610951576109516155ac565b905060200281019061096391906155c0565b61096d90806155de565b61097b9060608101906155f2565b61098860808b018b615566565b5f818110610998576109986155ac565b90506020028101906109aa91906155c0565b604001358181106109bd576109bd6155ac565b6109d39260206040909202019081019150614b2b565b6001600160a01b03168152602088810135910152905060605f6109f96080890189615566565b604080516001909201602002820181528501519093505f9250610a1d915082611b4c565b610a3a5760405163315f9e2360e21b815260040160405180910390fd5b5f5b610a4960808a018a615566565b905081108015610a6357506040840151610a63905f611b4c565b15610e7157610a7560808a018a615566565b82818110610a8557610a856155ac565b9050602002810190610a9791906155c0565b610aa090615638565b9550855f01519450835f01516001600160a01b03168560400151876020015181518110610acf57610acf6155ac565b60200260200101515f01516001600160a01b0316141580610b2a575083602001516001600160a01b03168560600151876040015181518110610b1357610b136155ac565b60200260200101515f01516001600160a01b031614155b15610b485760405163936bb5ad60e01b815260040160405180910390fd5b610b5b85876020015188604001516121bb565b5f610b6586611ab5565b5f81815260208190526040902054909150610bca578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a1610e68565b5f610c278789602001518a60400151338c606001515f67ffffffffffffffff811115610bf857610bf8614d08565b604051908082528060200260200182016040528015610c21578160200160208202803683370190505b5061222d565b90505f610c458c604001358360600151611b4c90919063ffffffff16565b15610c9b578751604080513381526001600160a01b03909216602083015281018490527fe3151dc8cb7a54ffc4baabd28c1f241c94d510b5e5b502491ac3cad6c16316d5906060015b60405180910390a1610e5a565b6040820151610caa905f611b4c565b1580610cc257506060820151610cc0905f611b4c565b155b15610d0f578751604080513381526001600160a01b03909216602083015281018490527f500b713857325f9e6dcb52ae832eca9109d107ed1aae9cb4928b4c1e13f051aa90606001610c8e565b600190505f808d6060016020810190610d2891906156ce565b15610d6e576040808a015190850151610d40916120bf565b6060850151909250610d5290836126f2565b60408a0151909150610d64908361273f565b60408a0152610dd5565b5f610d8a856040015186606001516126f290919063ffffffff16565b9050610da38a60400151826120bf90919063ffffffff16565b9150610dbc85606001518361276f90919063ffffffff16565b60408b0151909350610dce908361273f565b60408b0152505b610ddf8c8261279f565b9b50610deb8d8361279f565b9c50610df782856127cf565b610e018185612890565b7f194f1feb3b4d7076a2c272e774e792e0c48bb8c7aa1a9a3671c1cd6da9e6b4c1338c8484604051610e3694939291906157f6565b60405180910390a187516001018089526020028801849052610e5784612a3c565b50505b8480610e635750805b945050505b50600101610a3c565b505f610e8360808a0160608b016156ce565b610e8d5786610e8f565b875b9050610e9c818a35612c7f565b15610ec45760405163573b6f4160e01b81528935600482015260248101829052604401610316565b50610ed433846020015189612152565b505f9050610ee560a08a018a6158e0565b9050118015610ef15750805b15610f635760208301518351339163691f9ed7918a8a610f1460a08f018f6158e0565b6040518763ffffffff1660e01b8152600401610f35969594939291906154e4565b5f604051808303815f87803b158015610f4c575f80fd5b505af1158015610f5e573d5f803e3d5ffd5b505050505b610f7133845f015188611b86565b50505f5b8251811015610fa857610fa0838281518110610f9357610f936155ac565b6020026020010151612cb9565b600101610f75565b505050505050610fc460015f80516020615ecd83398151915255565b915091565b5f610fd2611a9a565b5f61102f61102a610fe38780615923565b610ff19060408101906158e0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612dc392505050565b612e34565b90505f811161105157604051632cff108b60e21b815260040160405180910390fd5b6001811161107257604051633c8270bd60e21b815260040160405180910390fd5b61107f60208601866155f2565b90505f036110a057604051636c44ef8f60e01b815260040160405180910390fd5b6110ad60408601866155f2565b90505f036110ce5760405163540e5f0b60e01b815260040160405180910390fd5b6040805160a081019091523381525f90602081016110ec8880615923565b6110f590615937565b815260200187806020019061110a91906155f2565b808060200260200160405190810160405280939291908181526020015f905b828210156111555761114660408302860136819003810190615942565b81526020019060010190611129565b505050918352505060200161116d60408901896155f2565b808060200260200160405190810160405280939291908181526020015f905b828210156111b8576111a960408302860136819003810190615942565b8152602001906001019061118c565b50505050508152602001876060013581525090505f6111d682611ab5565b5f818152602081905260409020549091501580156112f1575f828152602081905260409081902060019055835190517f87491344dfbcf91f6cbbc610cbbeedc85313d37a02df0c93527f7ea5f8db717f91611234918590879061595c565b60405180910390a15f61124a60a08a018a6158e0565b905011156112e65761129b61126260a08a018a6158e0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612e4e92505050565b82517fd46c2c56b35c8210e9e712ec3f02242d5fc90187c0ac8ed80cc33626846ec36990836112cd60a08c018c6158e0565b6040516112dd9493929190615983565b60405180910390a15b6112f1828888611ae4565b93505050506103bb60015f80516020615ecd83398151915255565b5f80808061132661131d86806155de565b61032c9061520a565b5f8181526020819052604090205490915060011461134d57505f92508291508190506113c7565b61137261135a86806155de565b6113639061520a565b866020013587604001356121bb565b5f6113b061138087806155de565b6113899061520a565b60208801356040890135336113a160608c018c615566565b6113aa916159b5565b5f610bf8565b905060018160400151826060015194509450945050505b9193909250565b604080515f8152602081019091526060908267ffffffffffffffff8111156113f8576113f8614d08565b60405190808252806020026020018201604052801561142b57816020015b60608152602001906001900390816114165790505b5091505f5b838110156114ac576114873086868481811061144e5761144e6155ac565b905060200281019061146091906158e0565b85604051602001611473939291906159d4565b604051602081830303815290604052612e79565b838281518110611499576114996155ac565b6020908102919091010152600101611430565b505092915050565b6114bc611a9a565b604080515f808252602082019092526114f4916114e9565b60608152602001906001900390816114d45790505b506104f88385615424565b61150a60015f80516020615ecd83398151915255565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa158015611552573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115769190615528565b5f036115a057604051633c5bf76960e21b81526001600160a01b0384166004820152602401610316565b505f92915050565b6115b0611a9a565b835185516001600160a01b039182169116036115df57604051630a98f1f360e21b815260040160405180910390fd5b83604001518360400135815181106115f9576115f96155ac565b60200260200101515f01516001600160a01b03168560600151846020013581518110611627576116276155ac565b60200260200101515f01516001600160a01b03161415806116a0575060408501518051843590811061165b5761165b6155ac565b60200260200101515f01516001600160a01b03168460600151846060013581518110611689576116896155ac565b60200260200101515f01516001600160a01b031614155b156116be5760405163936bb5ad60e01b815260040160405180910390fd5b84606001518360200135815181106116d8576116d86155ac565b60200260200101515f01516001600160a01b03168560400151845f013581518110611705576117056155ac565b60200260200101515f01516001600160a01b03160361173757604051631cd2f1c760e21b815260040160405180910390fd5b5f61174186611ab5565b5f818152602081905260409020549091506117a7578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a150611a84565b5f6117b186611ab5565b5f81815260208190526040902054909150611818578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a15050611a84565b7f6fa7f4c28634b0a9d6831401c45ae468195fb63aed07308935c35374ff5d9e393388888860405161184d94939291906159f7565b60405180910390a1505083515f906118719087908635906020880135908686610bf8565b90505f6118a086866040013587606001358a5f0151885f67ffffffffffffffff811115610bf857610bf8614d08565b90505f6118ad8383612f19565b90506118bc815f0151846127cf565b6118ca8160200151836127cf565b6118d8816040015184612890565b6118e6816060015183612890565b6118ef83612cb9565b6118f882612cb9565b606081015181515f9161190b919061273f565b90505f6119298360400151846020015161273f90919063ffffffff16565b9050611935825f612c7f565b806119455750611945815f612c7f565b1561196357604051630d86822160e01b815260040160405180910390fd5b611997338b606001518a6020013581518110611981576119816155ac565b60200260200101515f01518a6080013585611c06565b50506119cd338a606001518a60600135815181106119b7576119b76155ac565b60200260200101515f01518a60a0013584611c06565b5050604080513381528451602080830191909152850151818301529084015160608083019190915284015160808201527fd9fa84dd790c969daa5c33d8050dc06b4a9b59d5b42e2be5f5e8ae20447f618d925060a001905060405180910390a1611a3683612a3c565b611a3f82612a3c565b80516001600160e01b0316158015611a62575060208101516001600160e01b0316155b15611a80576040516321badf1f60e01b815260040160405180910390fd5b5050505b61051a60015f80516020615ecd83398151915255565b611aa2612f67565b60025f80516020615ecd83398151915255565b5f81604051602001611ac79190615a73565b604051602081830303815290604052805190602001209050919050565b604080516002815260208101859052338183015260608101909152611b1690611b0c906104d6565b6104f88385615424565b505050565b80611b16576040516305dbdfd960e41b81526001600160a01b03808516600483015283166024820152604401610316565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d611b7a84848484612f98565b12979650505050505050565b5f805f611b928561306c565b9050611b9e845f612c7f565b15611bbc57604051632eaefac360e21b815260040160405180910390fd5b5f80611bc886846130d2565b9150915080611bdd57611bda82615a85565b91505b8115611bf857611bf86001600160a01b038816893085612083565b50925090505b935093915050565b5f80611c128382612c7f565b15611c335760405163793a8f5560e01b815260048101849052602401610316565b83611c5157611c43868685612152565b505f9250829150611ced9050565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611c8b828661279f565b9050611c97815f612c7f565b15611cb85760405163c5e12af560e01b815260048101829052602401610316565b6001600160a01b038089165f908152600160209081526040808320938b16835292815282822089835290522081905590925090505b94509492505050565b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b8651811015611eba57868181518110611d5d57611d5d6155ac565b602002602001015193505f845f015160400151511115611eb2575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001611dd58d8a602001516130ff565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401611e009190615af5565b5f60405180830381865afa158015611e1a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611e419190810190615bed565b9150505f81511115611eb05784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490611e82908a908590600401615ca3565b5f604051808303815f87803b158015611e99575f80fd5b505af1158015611eab573d5f803e3d5ffd5b505050505b505b600101611d42565b5050505050505050565b5f8115611efe57506001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546103bb565b5f611f08846133e1565b6040516370a0823160e01b81526001600160a01b0387811660048301529192505f91611f8091908716906370a0823190602401602060405180830381865afa158015611f56573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f7a9190615528565b836133ed565b50604051636eb1769f60e11b81526001600160a01b0388811660048301523060248301529192505f91611fff919088169063dd62ed3e90604401602060405180830381865afa158015611fd5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ff99190615528565b846133ed565b506001600160a01b038089165f908152600160209081526040808320938b168352928152828220828052905220549091506120449061203e84846120bf565b9061279f565b93505050506103bb565b61205b838383600161342d565b611b1657604051635274afe760e01b81526001600160a01b0384166004820152602401610316565b61209184848484600161348f565b6120b957604051635274afe760e01b81526001600160a01b0385166004820152602401610316565b50505050565b5f6120ca8383612c7f565b6120d457816103bb565b5090919050565b5f806120e78382612c7f565b156121085760405163793a8f5560e01b815260048101849052602401610316565b8361211857611c43868685611b86565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611c8b828661273f565b5f805f61215e8561306c565b905061216a845f612c7f565b1561218857604051632d1671a360e11b815260040160405180910390fd5b5f61219385836130d2565b50905080156121b0576121b06001600160a01b038716888361204e565b969095509350505050565b826060015181815181106121d1576121d16155ac565b60200260200101515f01516001600160a01b0316836040015183815181106121fb576121fb6155ac565b60200260200101515f01516001600160a01b031603611b1657604051631cd2f1c760e21b815260040160405180910390fd5b6122356148a3565b60408051600480825260a082019092526060915f9190816020015b60608152602001906001900390816122505790505090506122a56122738a611ab5565b8a51604080516003815260208101939093526001600160a01b0391821683820152908916606083015260808201905290565b8160018003815181106122ba576122ba6155ac565b60200260200101819052505f6122ef8a604001518a815181106122df576122df6155ac565b60200260200101515f01516133e1565b90505f6123418b5f01518c604001518c8151811061230f5761230f6155ac565b60200260200101515f01518d604001518d81518110612330576123306155ac565b602002602001015160200151611ec4565b90506123d08b604001518b8151811061235c5761235c6155ac565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d604001518d8151811061238e5761238e6155ac565b602002602001015160200151845f801b60408051600581526020810196909652858101949094526060850192909252608084015260a083015260c08201905290565b836001600303815181106123e6576123e66155ac565b602002602001018190525050505f61240d8a6060015189815181106122df576122df6155ac565b90505f61244e8b5f01518c606001518b8151811061242d5761242d6155ac565b60200260200101515f01518d606001518c81518110612330576123306155ac565b905061249b8b606001518a81518110612469576124696155ac565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d606001518c8151811061238e5761238e6155ac565b836001600403815181106124b1576124b16155ac565b602002602001018190525050506124c881866130ff565b9150505f885f01516001600160a01b031690505f808a602001515f01516001600160a01b031663d04dfe236040518060e001604052808e60200151602001516001600160a01b0316815260200161252887305f9182526020526040902090565b81526020018e602001516040015181526020015f81526020018781526020015f67ffffffffffffffff81111561256057612560614d08565b604051908082528060200260200182016040528015612589578160200160208202803683370190505b508152602001898152506040518263ffffffff1660e01b81526004016125af9190615af5565b5f60405180830381865afa1580156125c9573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125f09190810190615bed565b9150915060028251101561261c578151604051630fbb8e5560e21b815260040161031691815260200190565b602082015160408301518551612670908790600490811061263f5761263f6155ac565b6020026020010151600381518110612659576126596155ac565b6020026020010151826120bf90919063ffffffff16565b60408051600281526020810183905280820185905260608101909152909150866002815181106126a2576126a26155ac565b60200260200101819052506040518060e001604052808e81526020018c81526020018281526020018381526020018781526020018681526020018481525096505050505050509695505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d8480612722868686866134fc565b915091505f612731838361361b565b9a9950505050505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613668565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613692565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061272286868686613bcf565b8181608001516004815181106127e7576127e76155ac565b6020026020010151600481518110612801576128016155ac565b6020026020010181815250506120b9815f01515f0151826080015160048151811061282e5761282e6155ac565b60200260200101515f81518110612847576128476155ac565b60200260200101515f1c8360800151600481518110612868576128686155ac565b6020026020010151600281518110612882576128826155ac565b6020026020010151856120db565b8181608001516003815181106128a8576128a86155ac565b60200260200101516004815181106128c2576128c26155ac565b6020908102919091010152805151608082015180515f919060039081106128eb576128eb6155ac565b60200260200101515f81518110612904576129046155ac565b60200260200101515f1c90505f8360800151600381518110612928576129286155ac565b6020026020010151600281518110612942576129426155ac565b602002602001015190505f801b81036129e95761295f855f612c7f565b156129805760405163793a8f5560e01b815260048101869052602401610316565b6001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546129b7908661279f565b6001600160a01b038085165f9081526001602090815260408083209387168352928152828220858352905220556129f8565b6129f583838388611c06565b50505b7f4cb6e22a3e7e651d7cf0376cff48f20f5007a54147777865be7f5f6c38c50f4a338560800151604051612a2d929190615cbb565b60405180910390a15050505050565b60c08101515115612ab6578051602090810151015160a082015160c083015160405163012c676d60e21b81526001600160a01b03909316926304b19db492612a88929091600401615ca3565b5f604051808303815f87803b158015612a9f575f80fd5b505af1158015612ab1573d5f803e3d5ffd5b505050505b5f815f0151602001515f01516001600160a01b031663d04dfe236040518060e00160405280855f015160200151602001516001600160a01b03168152602001612b0c8660a00151305f9182526020526040902090565b8152602001855f01516020015160400151815260200160018152602001856080015181526020015f67ffffffffffffffff811115612b4c57612b4c614d08565b604051908082528060200260200182016040528015612b75578160200160208202803683370190505b5081526020015f604051908082528060200260200182016040528015612ba5578160200160208202803683370190505b508152506040518263ffffffff1660e01b8152600401612bc59190615af5565b5f60405180830381865afa158015612bdf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612c069190810190615bed565b9150505f8151111561150a578151602090810151015160a083015160405163012c676d60e21b81526001600160a01b03909216916304b19db491612c4e918590600401615ca3565b5f604051808303815f87803b158015612c65575f80fd5b505af1158015612c77573d5f803e3d5ffd5b505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d612cad84848484612f98565b13979650505050505050565b5f8160800151600381518110612cd157612cd16155ac565b6020026020010151600281518110612ceb57612ceb6155ac565b602002602001015190505f801b810361150a57815151608083015180515f91906003908110612d1c57612d1c6155ac565b60200260200101515f81518110612d3557612d356155ac565b6020908102919091018101516001600160a01b038481165f9081526001845260408082209284168252918452818120878252909352909120549091506001600160e01b0381161561051a576001600160a01b038084165f9081526001602090815260408083209386168352928152828220878352905290812055612dba838383612152565b50505050505050565b6060604082511015612de257505060408051602081019091525f815290565b5f60208301519050602060408451612dfa91906159c1565b612e049190615cf0565b811115612e2057505060408051602081019091525f8152919050565b600181016020026020840101915050919050565b5f81515f03612e4457505f919050565b50602001515f1a90565b612e5781613ccd565b612e765780604051630c89984b60e31b81526004016103169190615d0f565b50565b60605f612e868484613cfb565b9050808015612ea757505f3d1180612ea757505f846001600160a01b03163b115b15612ebc57612eb4613d0e565b9150506102b4565b8015612ee657604051639996b31560e01b81526001600160a01b0385166004820152602401610316565b3d15612ef957612ef4613d27565b612f12565b60405163d6bda27560e01b815260040160405180910390fd5b5092915050565b604080516080810182525f808252602082018190529181018290526060810191909152612f468383613d32565b82526040820152612f578284613d32565b6020830152606082015292915050565b5f80516020615ecd83398151915254600203612f9657604051633ee5aeb560e01b815260040160405180910390fd5b565b5f8085158415178187128286121817858414178015612fbd5786859250925050611ced565b505f85841315612fd1575092949193919260015b8386035f8112604c8213178015613004578215612ff6575f8994509450505050611ced565b885f94509450505050611ced565b600a82900a8981028a82828161301c5761301c615cdc565b0514613048578415613038575f8b965096505050505050611ced565b8a5f965096505050505050611ced565b841561305d578896509450611ced9350505050565b9550879450611ced9350505050565b5f805f61307884613d9b565b9092509050600182600381111561309157613091615d21565b141580156130b057505f8260038111156130ad576130ad615d21565b14155b156103bb57838260405163ee07877f60e01b8152600401610316929190615d35565b5f806001600160e01b038416601b0b60e085901d6130f1828287613e28565b9350935050505b9250929050565b60605f825167ffffffffffffffff81111561311c5761311c614d08565b604051908082528060200260200182016040528015613145578160200160208202803683370190505b5090505f80845111613157575f61315d565b83516001015b85516001010190505f8167ffffffffffffffff81111561317f5761317f614d08565b6040519080825280602002602001820160405280156131b257816020015b606081526020019060019003908161319d5790505b5090505f6131d6604080516002815233602082015230818301526060810190915290565b8282815181106131e8576131e86155ac565b60200260200101819052505f5b8751811015613245578180600101925050878181518110613218576132186155ac565b6020026020010151838381518110613232576132326155ac565b60209081029190910101526001016131f5565b508551156133d757808060010191505083828281518110613268576132686155ac565b60200260200101819052505f5b86518110156133d557613324878281518110613293576132936155ac565b60200260200101515f01516133016132cf8a85815181106132b6576132b66155ac565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b898481518110613313576133136155ac565b602002602001015160400151613f8e565b61334457604051630a57f30960e31b815260048101829052602401610316565b868181518110613356576133566155ac565b60200260200101515f01516001600160a01b03165f1b85828151811061337e5761337e6155ac565b60200260200101818152505081806001019250508681815181106133a4576133a46155ac565b6020026020010151602001518383815181106133c2576133c26155ac565b6020908102919091010152600101613275565b505b5095945050505050565b5f805f61307884613ffe565b5f805f805f6133fc878761405d565b9250925092505f8061340e85856140a0565b915091508183801561341d5750815b9650965050505050509250929050565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316613483578383151615613477573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b6040516323b872dd60e01b5f8181526001600160a01b038781166004528616602452604485905291602083606481808c5af1925060015f511483166134eb5783831516156134df573d5f823e3d81fd5b5f883b113d1516831692505b604052505f60605295945050505050565b5f8085158415178015613514575f92505f9150613611565b61351e8487615d6e565b91505f61352a88614178565b90505f61353687614178565b90505f61354383836141a6565b5090505f6f0785ee10d5da46d900f436a000000000821115613578576f0785ee10d5da46d900f436a000000000820491506025015b670de0b6b3a764000082111561359957670de0b6b3a7640000820491506012015b633b9aca008211156135b257633b9aca00820491506009015b6127108211156135c757612710820491506004015b81156135db57600a820491506001016135c7565b6135e58187615d6e565b95506136078b8a61360187876135fc87600a615e6d565b6141c2565b8961428e565b9097509550505050505b5094509492505050565b5f805f61362885856140a0565b9150915080158015613638575081155b1561366057604051638eba4d0760e01b81526004810186905260248101859052604401610316565b509392505050565b5f80613674848461432e565b909450925061368586868686613bcf565b9150915094509492505050565b5f80835f036136be57604051637a97930f60e01b81526004810187905260248101869052604401610316565b855f036136cf57505f905080611ced565b5f805f806136dd8a8a614383565b919b50995091506136ee8888614383565b919950975090505f6136ff8b614178565b90505f61370b8a614178565b90507f161bcca7119915b50764b4abe86529797775a5f1719510000000000000000000604c81831015613ad057841561376257507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b9050604b613aa8565b6f4b3b4ca85a86c47a098a22400000000083101561388e57678ac7230489e800008310156137f2576402540be4008310156137c057620186a08310156137b05750620186a090506005613a69565b506402540be4009050600a613a69565b655af3107a40008310156137df5750655af3107a40009050600e613a69565b50678ac7230489e8000090506013613a69565b6b204fce5e3e250261100000008310156138445769152d02c7e14af680000083101561382d575069152d02c7e14af680000090506017613a69565b506b204fce5e3e250261100000009050601c613a69565b6d314dc6448d9338c15b0a0000000083101561387357506d314dc6448d9338c15b0a0000000090506021613a69565b506f4b3b4ca85a86c47a098a22400000000090506026613a69565b780197d4df19d605767337e9f14d3eec8920e4000000000000008310156139865773af298d050e4395d69670b12b7f41000000000000831015613921577172cb5bd86321e38cb6ce6682e8000000000083101561390257507172cb5bd86321e38cb6ce6682e800000000009050602b613a69565b5073af298d050e4395d69670b12b7f4100000000000090506030613a69565b76010b46c6cdd6e3e0828f4db456ff0c8ea0000000000000831015613962575076010b46c6cdd6e3e0828f4db456ff0c8ea000000000000090506035613a69565b50780197d4df19d605767337e9f14d3eec8920e4000000000000009050603a613a69565b7c03b58e88c75313ec9d329eaaa18fb92f75215b17100000000000000000831015613a1c577a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000008310156139f457507a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000009050603f613a69565b507c03b58e88c75313ec9d329eaaa18fb92f75215b1710000000000000000090506044613a69565b7e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000831015613a6957507e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000905060495b818311613a7e57600a820491505f1901613a69565b815f03613aa8576040516305e51ecb60e01b8152600481018d9052602481018c9052604401610316565b85613ad0576040516305e51ecb60e01b8152600481018f9052602481018e9052604401610316565b80600160ff1b018d12613ae757808d039c50613b25565b600160ff1b9c90038c015f811315613b2557806001600160ff1b03038b13613b1257998a0199613b25565b5f80995099505050505050505050611ced565b5f808e128015613b3457505f8c135b15613b5557600160ff1b8e01808d13613b4d575f613b51565b808d035b9150505b8b818f01039750613b728f8e613b6c8887896141c2565b8b61428e565b90995097505f811315613bbc57604c811315613b9c575f809a509a50505050505050505050611ced565b80600a0a8981613bae57613bae615cdc565b059850885f03613bbc575f97505b50969850949650611ced95505050505050565b5f8085158415178015613bfb57865f03613bef5784849250925050611ced565b86869250925050611ced565b613c0587876145dd565b9097509550613c1485856145dd565b909550935085841315613c28579395929492935b838603604c811115613c41578787935093505050611ced565b80600a0a8681613c5357613c53615cdc565b0595505086850180881860ff90811c151589881890911c15168015613cbc57876001600160ff1b0303613ca35760405163d556b11160e01b8152600481018a905260248101899052604401610316565b600a968790059690980586019760019790970196613cc0565b8198505b5096979596505050505050565b5f600882511015613cdf57505f919050565b506008015167ffffffffffffffff1667ff0a89c674ee78741490565b5f805f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f80613d4f846060015185604001516126f290919063ffffffff16565b915083604001519050613d6f836040015183611b4c90919063ffffffff16565b156130f85782604001519150613d9284606001518361276f90919063ffffffff16565b90509250929050565b5f80613da5614626565b60405163b7bad1b160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb93899063b7bad1b19060240160408051808303815f875af1158015613dfb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e1f9190615e78565b91509150915091565b5f805f851215613e5557604051634a7d166b60e01b81526004810186905260248101859052604401610316565b845f03613e6757505f90506001611bfe565b8460ff8416850185811215613e995760405163d556b11160e01b81526004810188905260248101879052604401610316565b5f805f831215613ee557604c19831215613ebc575f809550955050505050611bfe565b825f03600a0a9150818481613ed357613ed3615cdc565b0495505084029091149150611bfe9050565b5f831315613f7e57604d831315613f225760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b82600a0a9150815f1981613f3857613f38615cdc565b04841115613f6c5760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b5091909102925060019150611bfe9050565b8360019550955050505050611bfe565b5f836001600160a01b03163b5f03613fec575f80613fac85856146b1565b5090925090505f816003811115613fc557613fc5615d21565b148015613fe35750856001600160a01b0316826001600160a01b0316145b925050506103bb565b613ff78484846146f7565b90506103bb565b5f80614008614626565b604051630782d7e160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb938990630782d7e1906024016040805180830381865afa158015613dfb573d5f803e3d5ffd5b5f808060ff841681036001600160ff1b0386111561408f57600a860460018201600a88065f1493509350935050614099565b8593509150600190505b9250925092565b5f601b83900b8314838382614104577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e10000000000000000008605156140e457620186a0860595506005850194505b8586601b0b146140ff57600a860595508460010194506140e4565b61411a565b855f0361411a57505f9250600191506130f89050565b848560030b1461415d575f85121561413a57505f92508291506130f89050565b60405163d556b11160e01b81526004810183905260248101829052604401610316565b50506001600160e01b03841660e084901b1791509250929050565b5f8082121561419d57600160ff1b82036141975750600160ff1b919050565b505f0390565b5090565b919050565b5f805f1983850993909202808410938190039390930393915050565b5f805f6141cf86866141a6565b91509150815f036141f3578381816141e9576141e9615cdc565b04925050506103bb565b8382106142245760405163362ced0960e11b8152600481018790526024810186905260448101859052606401610316565b5f84868809600186198101871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103025f82900382900490920185841190960395909502919093039390930492909217029150509392505050565b5f805f858718121561430a576001600160ff1b038411156142f7576142bb6001600160ff1b036001615553565b84036142cf5750600160ff1b905081611ced565b6142da600a85615cf0565b6142e390615eb8565b6142ee846001615d6e565b91509150611ced565b61430084615eb8565b8391509150611ced565b6001600160ff1b03841115614324576142e3600a85615cf0565b5082905081611ced565b5f80600160ff1b8403614379576001600160ff1b03830361436c5760405163d556b11160e01b81526004810185905260248101849052604401610316565b600a840593508260010192505b50505f9190910391565b5f805f845f0361439b57505f91508190506001614099565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85055f03614588576f4b3b4ca85a86c47a098a22400000000085051580156143fd57507f80000000000000000000000000000000000000000000000000000000000000268412155b1561441e576f4b3b4ca85a86c47a098a224000000000850294506026840393505b7728c87cb5c89a2571ebfdcb54864ada834a00000000000000850515801561446657507f80000000000000000000000000000000000000000000000000000000000000138412155b1561447f57678ac7230489e80000850294506013840393505b7b097edd871cfda3a5697758bf0e3cbb5ac5741c64000000000000000085051580156144cb57507f800000000000000000000000000000000000000000000000000000000000000a8412155b156144e1576402540be40085029450600a840393505b7e3899162693736ac531a5a58f1fbb4b746504382ca7e4000000000000000000850515801561453057507f80000000000000000000000000000000000000000000000000000000000000028412155b15614546576064850294506002840393506144e1565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b850515801561457657506001600160ff1b018412155b1561458857600a850294506001840393505b600a808602908105861480156145a557506001600160ff1b018512155b156145b4578095506001850394505b50939492935050507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b8305151590565b5f805f805f6145ec8787614383565b9250925092508061461a576040516305e51ecb60e01b81526004810188905260248101879052604401610316565b50909590945092505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b158061467d575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b15612f96576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610316565b5f805f83516041036146e8576020840151604085015160608601515f1a6146da88828585614748565b955095509550505050614099565b505081515f9150600290614099565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561478157505f91506003905082614806565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156147d2573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166147fd57505f925060019150829050614806565b92505f91508190505b9450945094915050565b604051806080016040528061482361483c565b81526020015f81526020015f8152602001606081525090565b6040518060a001604052805f6001600160a01b0316815260200161488a60405180606001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b8152606060208201819052604082018190525f91015290565b6040518060e001604052806148b661483c565b81526020015f81526020015f80191681526020015f8019168152602001606081526020015f8152602001606081525090565b5f602082840312156148f8575f80fd5b81356001600160e01b0319811681146103bb575f80fd5b5f8083601f84011261491f575f80fd5b50813567ffffffffffffffff811115614936575f80fd5b6020830191508360208260051b85010111156130f8575f80fd5b5f805f60408486031215614962575f80fd5b833567ffffffffffffffff80821115614979575f80fd5b9085019060a0828803121561498c575f80fd5b909350602085013590808211156149a1575f80fd5b506149ae8682870161490f565b9497909650939450505050565b5f602082840312156149cb575f80fd5b5035919050565b6001600160a01b0381168114612e76575f80fd5b80356141a1816149d2565b5f805f805f60808688031215614a05575f80fd5b8535614a10816149d2565b94506020860135935060408601359250606086013567ffffffffffffffff811115614a39575f80fd5b614a458882890161490f565b969995985093965092949392505050565b5f805f60608486031215614a68575f80fd5b8335614a73816149d2565b92506020840135614a83816149d2565b929592945050506040919091013590565b5f805f805f60808688031215614aa8575f80fd5b8535614ab3816149d2565b94506020860135614ac3816149d2565b935060408601359250606086013567ffffffffffffffff80821115614ae6575f80fd5b818801915088601f830112614af9575f80fd5b813581811115614b07575f80fd5b896020828501011115614b18575f80fd5b9699959850939650602001949392505050565b5f60208284031215614b3b575f80fd5b81356103bb816149d2565b5f60c08284031215614b56575f80fd5b50919050565b5f60208284031215614b6c575f80fd5b813567ffffffffffffffff811115614b82575f80fd5b61052d84828501614b46565b5f805f60408486031215614ba0575f80fd5b833567ffffffffffffffff80821115614bb7575f80fd5b614bc387838801614b46565b945060208601359150808211156149a1575f80fd5b5f60208284031215614be8575f80fd5b813567ffffffffffffffff811115614bfe575f80fd5b8201608081850312156103bb575f80fd5b5f8060208385031215614c20575f80fd5b823567ffffffffffffffff811115614c36575f80fd5b614c428582860161490f565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614cd157603f19888603018452614cbf858351614c4e565b94509285019290850190600101614ca3565b5092979650505050505050565b5f8060408385031215614cef575f80fd5b8235614cfa816149d2565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b60405290565b6040805190810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b60405160a0810167ffffffffffffffff81118282101715614d3f57614d3f614d08565b604051601f8201601f1916810167ffffffffffffffff81118282101715614db457614db4614d08565b604052919050565b5f82601f830112614dcb575f80fd5b813567ffffffffffffffff811115614de557614de5614d08565b614df8601f8201601f1916602001614d8b565b818152846020838601011115614e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608284031215614e38575f80fd5b614e40614d1c565b90508135614e4d816149d2565b81526020820135614e5d816149d2565b6020820152604082013567ffffffffffffffff811115614e7b575f80fd5b614e8784828501614dbc565b60408301525092915050565b5f67ffffffffffffffff821115614eac57614eac614d08565b5060051b60200190565b5f60408284031215614ec6575f80fd5b614ece614d45565b90508135614edb816149d2565b808252506020820135602082015292915050565b5f82601f830112614efe575f80fd5b81356020614f13614f0e83614e93565b614d8b565b8083825260208201915060208460061b870101935086841115614f34575f80fd5b602086015b84811015614f5957614f4b8882614eb6565b835291830191604001614f39565b509695505050505050565b5f60a08284031215614f74575f80fd5b614f7c614d68565b9050614f87826149e6565b8152602082013567ffffffffffffffff80821115614fa3575f80fd5b614faf85838601614e28565b60208401526040840135915080821115614fc7575f80fd5b614fd385838601614eef565b60408401526060840135915080821115614feb575f80fd5b50614ff884828501614eef565b6060830152506080820135608082015292915050565b5f61501b614f0e84614e93565b8381529050602080820190600585811b850187811115615039575f80fd5b855b8181101561512657803567ffffffffffffffff8082111561505a575f80fd5b908801906060828c03121561506d575f80fd5b615075614d1c565b8235615080816149d2565b81528287013582811115615092575f80fd5b8301601f81018d136150a2575f80fd5b80356150b0614f0e82614e93565b81815290881b8201890190898101908f8311156150cb575f80fd5b928a01925b828410156150e95783358252928a0192908a01906150d0565b848b01525060409150508381013583811115615103575f80fd5b61510f8e828701614dbc565b91830191909152508752505093830193830161503b565b50505050509392505050565b5f82601f830112615141575f80fd5b6103bb8383356020850161500e565b5f805f805f6101408688031215615165575f80fd5b853567ffffffffffffffff8082111561517c575f80fd5b61518889838a01614f64565b9650602088013591508082111561519d575f80fd5b6151a989838a01614f64565b95506151b88960408a01614b46565b94506101008801359150808211156151ce575f80fd5b6151da89838a01615132565b93506101208801359150808211156151f0575f80fd5b506151fd88828901615132565b9150509295509295909350565b5f6102b43683614f64565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f8135615249816149d2565b6001600160a01b039081168452602083013590615265826149d2565b166020840152604082013536839003601e19018112615282575f80fd5b820160208101903567ffffffffffffffff81111561529e575f80fd5b8036038213156152ac575f80fd5b606060408601526152c1606086018284615215565b95945050505050565b5f808335601e198436030181126152df575f80fd5b830160208101925035905067ffffffffffffffff8111156152fe575f80fd5b8060061b36038213156130f8575f80fd5b8183525f60208085019450825f5b85811015615355578135615330816149d2565b6001600160a01b0316875281830135838801526040968701969091019060010161531d565b509495945050505050565b5f6001600160a01b038086168352846020840152606060408401528335615386816149d2565b166060830152602083013536849003605e190181126153a3575f80fd5b60a060808401526153ba610100840185830161523d565b90506153c960408501856152ca565b605f19808685030160a08701526153e184838561530f565b93506153f060608801886152ca565b93509150808685030160c08701525061540a83838361530f565b92505050608084013560e084015280915050949350505050565b5f615431614f0e84614e93565b80848252602080830192508560051b85013681111561544e575f80fd5b855b818110156154d857803567ffffffffffffffff8082111561546f575f80fd5b818901915060408236031215615483575f80fd5b61548b614d45565b823582811115615499575f80fd5b6154a536828601614e28565b82525085830135828111156154b8575f80fd5b6154c436828601615132565b828801525087525050938201938201615450565b50919695505050505050565b5f6001600160a01b03808916835280881660208401525085604083015284606083015260a0608083015261551c60a083018486615215565b98975050505050505050565b5f60208284031215615538575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102b4576102b461553f565b5f808335601e1984360301811261557b575f80fd5b83018035915067ffffffffffffffff821115615595575f80fd5b6020019150600581901b36038213156130f8575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e198336030181126155d4575f80fd5b9190910192915050565b5f8235609e198336030181126155d4575f80fd5b5f808335601e19843603018112615607575f80fd5b83018035915067ffffffffffffffff821115615621575f80fd5b6020019150600681901b36038213156130f8575f80fd5b5f60808236031215615648575f80fd5b6040516080810167ffffffffffffffff828210818311171561566c5761566c614d08565b816040528435915080821115615680575f80fd5b61568c36838701614f64565b8352602085013560208401526040850135604084015260608501359150808211156156b5575f80fd5b506156c236828601615132565b60608301525092915050565b5f602082840312156156de575f80fd5b813580151581146103bb575f80fd5b5f815180845260208085019450602084015f5b8381101561535557815180516001600160a01b031688528301518388015260409096019590820190600101615700565b5f6001600160a01b03808351168452602083015160a060208601528181511660a08601528160208201511660c08601526040810151915050606060e085015261577d610100850182614c4e565b90506040830151848203604086015261579682826156ed565b915050606083015184820360608601526157b082826156ed565b915050608083015160808501528091505092915050565b5f815180845260208085019450602084015f5b83811015615355578151875295820195908201906001016157da565b5f6001600160a01b03808716835260206080818501528651608080860152615822610100860182615730565b90508188015160a086015260408089015160c08701526060808a0151607f198885030160e08901528381518086528686019150868160051b87010187840193505f5b828110156158be57601f1988830301845284518a815116835289810151878b850152615892888501826157c7565b91890151848303858b01529190506158aa8183614c4e565b968b0196958b019593505050600101615864565b5080995050505050505050505083604083015282606083015295945050505050565b5f808335601e198436030181126158f5575f80fd5b83018035915067ffffffffffffffff82111561590f575f80fd5b6020019150368190038213156130f8575f80fd5b5f8235605e198336030181126155d4575f80fd5b5f6102b43683614e28565b5f60408284031215615952575f80fd5b6103bb8383614eb6565b6001600160a01b0384168152826020820152606060408201525f6152c16060830184615730565b6001600160a01b0385168152836020820152606060408201525f6159ab606083018486615215565b9695505050505050565b5f6103bb36848461500e565b818103818111156102b4576102b461553f565b828482375f8382015f815283518060208601835e5f910190815295945050505050565b5f6101206001600160a01b0387168352806020840152615a1981840187615730565b90508281036040840152615a2d8186615730565b9150508235606083015260208301356080830152604083013560a0830152606083013560c0830152608083013560e083015260a083013561010083015295945050505050565b602081525f6103bb6020830184615730565b5f60018201615a9657615a9661553f565b5060010190565b5f8282518085526020808601955060208260051b840101602086015f5b84811015615ae857601f19868403018952615ad68383516157c7565b98840198925090830190600101615aba565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e06060840152615b2e610100840182614c4e565b9050606084015160808401526080840151601f19808584030160a0860152615b568383615a9d565b925060a08601519150808584030160c0860152615b7383836157c7565b925060c08601519150808584030160e0860152506152c182826157c7565b5f82601f830112615ba0575f80fd5b81516020615bb0614f0e83614e93565b8083825260208201915060208460051b870101935086841115615bd1575f80fd5b602086015b84811015614f595780518352918301918301615bd6565b5f8060408385031215615bfe575f80fd5b825167ffffffffffffffff80821115615c15575f80fd5b818501915085601f830112615c28575f80fd5b81516020615c38614f0e83614e93565b82815260059290921b84018101918181019089841115615c56575f80fd5b948201945b83861015615c7457855182529482019490820190615c5b565b91880151919650909350505080821115615c8c575f80fd5b50615c9985828601615b91565b9150509250929050565b828152604060208201525f61052d60408301846157c7565b6001600160a01b0383168152604060208201525f61052d6040830184615a9d565b634e487b7160e01b5f52601260045260245ffd5b5f82615d0a57634e487b7160e01b5f52601260045260245ffd5b500490565b602081525f6103bb6020830184614c4e565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040810160048310615d6157634e487b7160e01b5f52602160045260245ffd5b8260208301529392505050565b8082018281125f8312801582168215821617156114ac576114ac61553f565b600181815b80851115615dc757815f1904821115615dad57615dad61553f565b80851615615dba57918102915b93841c9390800290615d92565b509250929050565b5f82615ddd575060016102b4565b81615de957505f6102b4565b8160018114615dff5760028114615e0957615e25565b60019150506102b4565b60ff841115615e1a57615e1a61553f565b50506001821b6102b4565b5060208310610133831016604e8410600b8410161715615e48575081810a6102b4565b615e528383615d8d565b805f1904821115615e6557615e6561553f565b029392505050565b5f6103bb8383615dcf565b5f8060408385031215615e89575f80fd5b825160048110615e97575f80fd5b602084015190925060ff81168114615ead575f80fd5b809150509250929050565b5f600160ff1b82016141975761419761553f56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00"; + hex"608060405234801561000f575f80fd5b50600436106100f0575f3560e01c8063613255ab11610093578063ac9650d811610063578063ac9650d81461022b578063d7e442ec1461024b578063d9d98ce41461025e578063fa50118214610271575f80fd5b8063613255ab146101ad57806369c72856146101c0578063709fb8a5146101e85780639235084d146101fb575f80fd5b80632fbc4ba0116100ce5780632fbc4ba01461015157806341d1514f146101665780635cffe9de14610187578063607461191461019a575f80fd5b806301ffc9a7146100f45780631f69cb751461011c5780632cb77e9f1461012f575b5f80fd5b610107610102366004614a14565b610284565b60405190151581526020015b60405180910390f35b61010761012a366004614a7c565b6102ba565b61010761013d366004614ae7565b5f9081526020819052604090205460011490565b61016461015f366004614b1d565b6103c2565b005b610179610174366004614b82565b610521565b604051908152602001610113565b610107610195366004614bc0565b610535565b6101646101a8366004614b1d565b610635565b6101796101bb366004614c57565b6107c8565b6101d36101ce366004614c88565b610830565b60408051928352602083019190915201610113565b6101076101f6366004614cba565b610fc9565b61020e610209366004614d04565b61130c565b604080519315158452602084019290925290820152606001610113565b61023e610239366004614d3b565b6113ce565b6040516101139190614da8565b610164610259366004614d3b565b6114b4565b61017961026c366004614e0a565b61150e565b61016461027f36600461527c565b6115a8565b5f6001600160e01b0319821663e414309160e01b14806102b457506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f6102c3611a9a565b6102d06020850185614c57565b6001600160a01b0316336001600160a01b03161461031f576102f56020850185614c57565b6040516335252be360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b5f61033161032c86615336565b611ab5565b5f818152602081905260409020549091505f19016103a4575f818152602081905260408082209190915551600192507f09d18501db0080ca2d6cd7c17fa7255daff4b2d503ea93b76ff68b6752ea8e63906103919033908490899061548c565b60405180910390a16103a4818585611ae4565b506103bb60015f80516020615ff983398151915255565b9392505050565b6103ca611a9a565b3385856103d8838383611b1b565b6103e2865f611b4c565b610417576040516306dde9c360e41b81523360048201526001600160a01b038916602482015260448101889052606401610316565b5f80610424338b8a611b86565b604080513381526001600160a01b038e1660208201529081018c90526060810183905291935091507f7f9dfa19cf1cc2f806f2f860fbc9c056b601fb1afc0e9b843dfe5c63616268e69060800160405180910390a15f80610487338d8d8d611cbe565b909250905087156104fd5760408051600581526001600160a01b038e1660208201528082018d9052606081018490526080810183905260ff851660a082015260c081019091526104fd906104ee905b60408051600181526020810192909252818101905290565b6104f88a8c615550565b611dae565b5050505050505061051a60015f80516020615ff983398151915255565b5050505050565b5f61052d848484611f7c565b949350505050565b5f61054a6001600160a01b0386168786612106565b6040516323e30c8b60e01b81525f906001600160a01b038816906323e30c8b906105829033908a908a9087908b908b90600401615610565b6020604051808303815f875af115801561059e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c29190615654565b90507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9811461060757604051630b6c58a960e31b815260048101829052602401610316565b61062887306106165f8961567f565b6001600160a01b038a1692919061213b565b5060019695505050505050565b61063d611a9a565b33858561064b838383611b1b565b5f8080806106598a82611b4c565b61068d57604051623a3a4d60e21b81523360048201526001600160a01b038d166024820152604481018c9052606401610316565b5f610699338e8e611f7c565b90506106a58b82612177565b94506106b3338e8e88612193565b90935091505f6106c4338f8861220a565b80965081925050507f8045c25080b0868951141ed0a91720bcad09a8364a2b3109ee1fd49c1f0bc8b8338f8f8f8a86604051610736969594939291906001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b60405180910390a1505060408051600681526001600160a01b038e1660208201528082018d9052606081018490526080810183905260a081018c905260ff851660c0820152600160e08201908152610100820182905261012082019092529089156107a9576107a9816104f88c8e615550565b50505050505050505061051a60015f80516020615ff983398151915255565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa15801561080c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b49190615654565b5f8061083a611a9a565b6108476080840184615692565b90505f0361086857604051639c95219f60e01b815260040160405180910390fd5b61087061493c565b610878614968565b5f60405180606001604052808780608001906108949190615692565b5f8181106108a4576108a46156d8565b90506020028101906108b691906156ec565b6108c0908061570a565b6108ce90604081019061571e565b6108db60808b018b615692565b5f8181106108eb576108eb6156d8565b90506020028101906108fd91906156ec565b60200135818110610910576109106156d8565b6109269260206040909202019081019150614c57565b6001600160a01b031681526020016109416080890189615692565b5f818110610951576109516156d8565b905060200281019061096391906156ec565b61096d908061570a565b61097b90606081019061571e565b61098860808b018b615692565b5f818110610998576109986156d8565b90506020028101906109aa91906156ec565b604001358181106109bd576109bd6156d8565b6109d39260206040909202019081019150614c57565b6001600160a01b03168152602088810135910152905060605f6109f96080890189615692565b604080516001909201602002820181528501519093505f9250610a1d915082611b4c565b610a3a5760405163315f9e2360e21b815260040160405180910390fd5b5f5b610a4960808a018a615692565b905081108015610a6357506040840151610a63905f611b4c565b15610e7157610a7560808a018a615692565b82818110610a8557610a856156d8565b9050602002810190610a9791906156ec565b610aa090615764565b9550855f01519450835f01516001600160a01b03168560400151876020015181518110610acf57610acf6156d8565b60200260200101515f01516001600160a01b0316141580610b2a575083602001516001600160a01b03168560600151876040015181518110610b1357610b136156d8565b60200260200101515f01516001600160a01b031614155b15610b485760405163936bb5ad60e01b815260040160405180910390fd5b610b5b85876020015188604001516122e7565b5f610b6586611ab5565b5f81815260208190526040902054909150610bca578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a1610e68565b5f610c278789602001518a60400151338c606001515f67ffffffffffffffff811115610bf857610bf8614e34565b604051908082528060200260200182016040528015610c21578160200160208202803683370190505b50612359565b90505f610c458c604001358360600151611b4c90919063ffffffff16565b15610c9b578751604080513381526001600160a01b03909216602083015281018490527fe3151dc8cb7a54ffc4baabd28c1f241c94d510b5e5b502491ac3cad6c16316d5906060015b60405180910390a1610e5a565b6040820151610caa905f611b4c565b1580610cc257506060820151610cc0905f611b4c565b155b15610d0f578751604080513381526001600160a01b03909216602083015281018490527f500b713857325f9e6dcb52ae832eca9109d107ed1aae9cb4928b4c1e13f051aa90606001610c8e565b600190505f808d6060016020810190610d2891906157fa565b15610d6e576040808a015190850151610d4091612177565b6060850151909250610d52908361281e565b60408a0151909150610d64908361286b565b60408a0152610dd5565b5f610d8a8560400151866060015161281e90919063ffffffff16565b9050610da38a604001518261217790919063ffffffff16565b9150610dbc85606001518361289b90919063ffffffff16565b60408b0151909350610dce908361286b565b60408b0152505b610ddf8c826128cb565b9b50610deb8d836128cb565b9c50610df782856128fb565b610e0181856129bc565b7f194f1feb3b4d7076a2c272e774e792e0c48bb8c7aa1a9a3671c1cd6da9e6b4c1338c8484604051610e369493929190615922565b60405180910390a187516001018089526020028801849052610e5784612b68565b50505b8480610e635750805b945050505b50600101610a3c565b505f610e8360808a0160608b016157fa565b610e8d5786610e8f565b875b9050610e9c818a35612dab565b15610ec45760405163573b6f4160e01b81528935600482015260248101829052604401610316565b50610ed43384602001518961220a565b505f9050610ee560a08a018a615a0c565b9050118015610ef15750805b15610f635760208301518351339163691f9ed7918a8a610f1460a08f018f615a0c565b6040518763ffffffff1660e01b8152600401610f3596959493929190615610565b5f604051808303815f87803b158015610f4c575f80fd5b505af1158015610f5e573d5f803e3d5ffd5b505050505b610f7133845f015188611b86565b50505f5b8251811015610fa857610fa0838281518110610f9357610f936156d8565b6020026020010151612de5565b600101610f75565b505050505050610fc460015f80516020615ff983398151915255565b915091565b5f610fd2611a9a565b5f61102f61102a610fe38780615a4f565b610ff1906040810190615a0c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612eef92505050565b612f60565b90505f811161105157604051632cff108b60e21b815260040160405180910390fd5b6001811161107257604051633c8270bd60e21b815260040160405180910390fd5b61107f602086018661571e565b90505f036110a057604051636c44ef8f60e01b815260040160405180910390fd5b6110ad604086018661571e565b90505f036110ce5760405163540e5f0b60e01b815260040160405180910390fd5b6040805160a081019091523381525f90602081016110ec8880615a4f565b6110f590615a63565b815260200187806020019061110a919061571e565b808060200260200160405190810160405280939291908181526020015f905b828210156111555761114660408302860136819003810190615a6e565b81526020019060010190611129565b505050918352505060200161116d604089018961571e565b808060200260200160405190810160405280939291908181526020015f905b828210156111b8576111a960408302860136819003810190615a6e565b8152602001906001019061118c565b50505050508152602001876060013581525090505f6111d682611ab5565b5f818152602081905260409020549091501580156112f1575f828152602081905260409081902060019055835190517f87491344dfbcf91f6cbbc610cbbeedc85313d37a02df0c93527f7ea5f8db717f916112349185908790615a88565b60405180910390a15f61124a60a08a018a615a0c565b905011156112e65761129b61126260a08a018a615a0c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612f7a92505050565b82517fd46c2c56b35c8210e9e712ec3f02242d5fc90187c0ac8ed80cc33626846ec36990836112cd60a08c018c615a0c565b6040516112dd9493929190615aaf565b60405180910390a15b6112f1828888611ae4565b93505050506103bb60015f80516020615ff983398151915255565b5f80808061132661131d868061570a565b61032c90615336565b5f8181526020819052604090205490915060011461134d57505f92508291508190506113c7565b61137261135a868061570a565b61136390615336565b866020013587604001356122e7565b5f6113b0611380878061570a565b61138990615336565b60208801356040890135336113a160608c018c615692565b6113aa91615ae1565b5f610bf8565b905060018160400151826060015194509450945050505b9193909250565b604080515f8152602081019091526060908267ffffffffffffffff8111156113f8576113f8614e34565b60405190808252806020026020018201604052801561142b57816020015b60608152602001906001900390816114165790505b5091505f5b838110156114ac576114873086868481811061144e5761144e6156d8565b90506020028101906114609190615a0c565b8560405160200161147393929190615b00565b604051602081830303815290604052612fa5565b838281518110611499576114996156d8565b6020908102919091010152600101611430565b505092915050565b6114bc611a9a565b604080515f808252602082019092526114f4916114e9565b60608152602001906001900390816114d45790505b506104f88385615550565b61150a60015f80516020615ff983398151915255565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa158015611552573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115769190615654565b5f036115a057604051633c5bf76960e21b81526001600160a01b0384166004820152602401610316565b505f92915050565b6115b0611a9a565b835185516001600160a01b039182169116036115df57604051630a98f1f360e21b815260040160405180910390fd5b83604001518360400135815181106115f9576115f96156d8565b60200260200101515f01516001600160a01b03168560600151846020013581518110611627576116276156d8565b60200260200101515f01516001600160a01b03161415806116a0575060408501518051843590811061165b5761165b6156d8565b60200260200101515f01516001600160a01b03168460600151846060013581518110611689576116896156d8565b60200260200101515f01516001600160a01b031614155b156116be5760405163936bb5ad60e01b815260040160405180910390fd5b84606001518360200135815181106116d8576116d86156d8565b60200260200101515f01516001600160a01b03168560400151845f013581518110611705576117056156d8565b60200260200101515f01516001600160a01b03160361173757604051631cd2f1c760e21b815260040160405180910390fd5b5f61174186611ab5565b5f818152602081905260409020549091506117a7578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a150611a84565b5f6117b186611ab5565b5f81815260208190526040902054909150611818578551604080513381526001600160a01b03909216602083015281018290527fb70c12fa453793fa6818ec07c91e74363a47aa6a6829dcd9533937fdf30314f39060600160405180910390a15050611a84565b7f6fa7f4c28634b0a9d6831401c45ae468195fb63aed07308935c35374ff5d9e393388888860405161184d9493929190615b23565b60405180910390a1505083515f906118719087908635906020880135908686610bf8565b90505f6118a086866040013587606001358a5f0151885f67ffffffffffffffff811115610bf857610bf8614e34565b90505f6118ad8383613045565b90506118bc815f0151846128fb565b6118ca8160200151836128fb565b6118d88160400151846129bc565b6118e68160600151836129bc565b6118ef83612de5565b6118f882612de5565b606081015181515f9161190b919061286b565b90505f6119298360400151846020015161286b90919063ffffffff16565b9050611935825f612dab565b806119455750611945815f612dab565b1561196357604051630d86822160e01b815260040160405180910390fd5b611997338b606001518a6020013581518110611981576119816156d8565b60200260200101515f01518a6080013585611cbe565b50506119cd338a606001518a60600135815181106119b7576119b76156d8565b60200260200101515f01518a60a0013584611cbe565b5050604080513381528451602080830191909152850151818301529084015160608083019190915284015160808201527fd9fa84dd790c969daa5c33d8050dc06b4a9b59d5b42e2be5f5e8ae20447f618d925060a001905060405180910390a1611a3683612b68565b611a3f82612b68565b80516001600160e01b0316158015611a62575060208101516001600160e01b0316155b15611a80576040516321badf1f60e01b815260040160405180910390fd5b5050505b61051a60015f80516020615ff983398151915255565b611aa2613093565b60025f80516020615ff983398151915255565b5f81604051602001611ac79190615b9f565b604051602081830303815290604052805190602001209050919050565b604080516002815260208101859052338183015260608101909152611b1690611b0c906104d6565b6104f88385615550565b505050565b80611b16576040516305dbdfd960e41b81526001600160a01b03808516600483015283166024820152604401610316565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d611b7a848484846130c4565b12979650505050505050565b5f805f611b9285613198565b9050611b9e845f612dab565b15611bbc57604051632eaefac360e21b815260040160405180910390fd5b6001600160a01b038087165f90815260026020908152604080832093891683529290529081205490611bee868361286b565b90505f80611bfc8382611b4c565b15611c62575f611c0c84876131fe565b909350905080611c2257611c1f83615bb1565b92505b5f611c2d8a886131fe565b50905080611c3c85600161567f565b1015611c4a57809350600192505b611c5f6001600160a01b038c168d308761213b565b50505b5f611c6d838761322b565b50905081611c8457611c7f818561286b565b611c86565b845b6001600160a01b03808d165f908152600260209081526040808320938f1683529290522055509095509293505050505b935093915050565b5f80611cca8382612dab565b15611ceb5760405163793a8f5560e01b815260048101849052602401610316565b83611d0957611cfb86868561220a565b505f9250829150611da59050565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611d4382866128cb565b9050611d4f815f612dab565b15611d705760405163c5e12af560e01b815260048101829052602401610316565b6001600160a01b038089165f908152600160209081526040808320938b16835292815282822089835290522081905590925090505b94509492505050565b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b8651811015611f7257868181518110611e1557611e156156d8565b602002602001015193505f845f015160400151511115611f6a575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001611e8d8d8a6020015161326b565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401611eb89190615c21565b5f60405180830381865afa158015611ed2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611ef99190810190615d19565b9150505f81511115611f685784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490611f3a908a908590600401615dcf565b5f604051808303815f87803b158015611f51575f80fd5b505af1158015611f63573d5f803e3d5ffd5b505050505b505b600101611dfa565b5050505050505050565b5f8115611fb657506001600160a01b038084165f9081526001602090815260408083209386168352928152828220848352905220546103bb565b5f611fc08461354d565b6040516370a0823160e01b81526001600160a01b0387811660048301529192505f9161203891908716906370a0823190602401602060405180830381865afa15801561200e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120329190615654565b8361322b565b50604051636eb1769f60e11b81526001600160a01b0388811660048301523060248301529192505f916120b7919088169063dd62ed3e90604401602060405180830381865afa15801561208d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120b19190615654565b8461322b565b506001600160a01b038089165f908152600160209081526040808320938b168352928152828220828052905220549091506120fc906120f68484612177565b906128cb565b93505050506103bb565b6121138383836001613559565b611b1657604051635274afe760e01b81526001600160a01b0384166004820152602401610316565b6121498484848460016135bb565b61217157604051635274afe760e01b81526001600160a01b0385166004820152602401610316565b50505050565b5f6121828383612dab565b61218c57816103bb565b5090919050565b5f8061219f8382612dab565b156121c05760405163793a8f5560e01b815260048101849052602401610316565b836121d057611cfb868685611b86565b6001600160a01b038087165f908152600160209081526040808320938916835292815282822087835290529081205490611d43828661286b565b5f805f61221685613198565b9050612222845f612dab565b1561224057604051632d1671a360e11b815260040160405180910390fd5b6001600160a01b038087165f9081526002602090815260408083209389168352929052908120546122729086906128cb565b90505f61227f82846131fe565b5090505f61228d828561322b565b50905061229a838261286b565b6001600160a01b03808b165f908152600260209081526040808320938d168352929052205581156122d9576122d96001600160a01b0389168a84612106565b509791965090945050505050565b826060015181815181106122fd576122fd6156d8565b60200260200101515f01516001600160a01b031683604001518381518110612327576123276156d8565b60200260200101515f01516001600160a01b031603611b1657604051631cd2f1c760e21b815260040160405180910390fd5b6123616149cf565b60408051600480825260a082019092526060915f9190816020015b606081526020019060019003908161237c5790505090506123d161239f8a611ab5565b8a51604080516003815260208101939093526001600160a01b0391821683820152908916606083015260808201905290565b8160018003815181106123e6576123e66156d8565b60200260200101819052505f61241b8a604001518a8151811061240b5761240b6156d8565b60200260200101515f015161354d565b90505f61246d8b5f01518c604001518c8151811061243b5761243b6156d8565b60200260200101515f01518d604001518d8151811061245c5761245c6156d8565b602002602001015160200151611f7c565b90506124fc8b604001518b81518110612488576124886156d8565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d604001518d815181106124ba576124ba6156d8565b602002602001015160200151845f801b60408051600581526020810196909652858101949094526060850192909252608084015260a083015260c08201905290565b83600160030381518110612512576125126156d8565b602002602001018190525050505f6125398a60600151898151811061240b5761240b6156d8565b90505f61257a8b5f01518c606001518b81518110612559576125596156d8565b60200260200101515f01518d606001518c8151811061245c5761245c6156d8565b90506125c78b606001518a81518110612595576125956156d8565b60200260200101515f01516001600160a01b03165f1b8360ff165f1b8d606001518c815181106124ba576124ba6156d8565b836001600403815181106125dd576125dd6156d8565b602002602001018190525050506125f4818661326b565b9150505f885f01516001600160a01b031690505f808a602001515f01516001600160a01b031663d04dfe236040518060e001604052808e60200151602001516001600160a01b0316815260200161265487305f9182526020526040902090565b81526020018e602001516040015181526020015f81526020018781526020015f67ffffffffffffffff81111561268c5761268c614e34565b6040519080825280602002602001820160405280156126b5578160200160208202803683370190505b508152602001898152506040518263ffffffff1660e01b81526004016126db9190615c21565b5f60405180830381865afa1580156126f5573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261271c9190810190615d19565b91509150600282511015612748578151604051630fbb8e5560e21b815260040161031691815260200190565b60208201516040830151855161279c908790600490811061276b5761276b6156d8565b6020026020010151600381518110612785576127856156d8565b60200260200101518261217790919063ffffffff16565b60408051600281526020810183905280820185905260608101909152909150866002815181106127ce576127ce6156d8565b60200260200101819052506040518060e001604052808e81526020018c81526020018281526020018381526020018781526020018681526020018481525096505050505050509695505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613628565b915091505f61285d8383613747565b9a9950505050505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613794565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e868686866137be565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d848061284e86868686613cfb565b818160800151600481518110612913576129136156d8565b602002602001015160048151811061292d5761292d6156d8565b602002602001018181525050612171815f01515f0151826080015160048151811061295a5761295a6156d8565b60200260200101515f81518110612973576129736156d8565b60200260200101515f1c8360800151600481518110612994576129946156d8565b60200260200101516002815181106129ae576129ae6156d8565b602002602001015185612193565b8181608001516003815181106129d4576129d46156d8565b60200260200101516004815181106129ee576129ee6156d8565b6020908102919091010152805151608082015180515f91906003908110612a1757612a176156d8565b60200260200101515f81518110612a3057612a306156d8565b60200260200101515f1c90505f8360800151600381518110612a5457612a546156d8565b6020026020010151600281518110612a6e57612a6e6156d8565b602002602001015190505f801b8103612b1557612a8b855f612dab565b15612aac5760405163793a8f5560e01b815260048101869052602401610316565b6001600160a01b038084165f908152600160209081526040808320938616835292815282822084835290522054612ae390866128cb565b6001600160a01b038085165f908152600160209081526040808320938716835292815282822085835290522055612b24565b612b2183838388611cbe565b50505b7f4cb6e22a3e7e651d7cf0376cff48f20f5007a54147777865be7f5f6c38c50f4a338560800151604051612b59929190615de7565b60405180910390a15050505050565b60c08101515115612be2578051602090810151015160a082015160c083015160405163012c676d60e21b81526001600160a01b03909316926304b19db492612bb4929091600401615dcf565b5f604051808303815f87803b158015612bcb575f80fd5b505af1158015612bdd573d5f803e3d5ffd5b505050505b5f815f0151602001515f01516001600160a01b031663d04dfe236040518060e00160405280855f015160200151602001516001600160a01b03168152602001612c388660a00151305f9182526020526040902090565b8152602001855f01516020015160400151815260200160018152602001856080015181526020015f67ffffffffffffffff811115612c7857612c78614e34565b604051908082528060200260200182016040528015612ca1578160200160208202803683370190505b5081526020015f604051908082528060200260200182016040528015612cd1578160200160208202803683370190505b508152506040518263ffffffff1660e01b8152600401612cf19190615c21565b5f60405180830381865afa158015612d0b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612d329190810190615d19565b9150505f8151111561150a578151602090810151015160a083015160405163012c676d60e21b81526001600160a01b03909216916304b19db491612d7a918590600401615dcf565b5f604051808303815f87803b158015612d91575f80fd5b505af1158015612da3573d5f803e3d5ffd5b505050505050565b5f6001600160e01b03838116601b90810b9160e086811d9291861690910b9085901d612dd9848484846130c4565b13979650505050505050565b5f8160800151600381518110612dfd57612dfd6156d8565b6020026020010151600281518110612e1757612e176156d8565b602002602001015190505f801b810361150a57815151608083015180515f91906003908110612e4857612e486156d8565b60200260200101515f81518110612e6157612e616156d8565b6020908102919091018101516001600160a01b038481165f9081526001845260408082209284168252918452818120878252909352909120549091506001600160e01b0381161561051a576001600160a01b038084165f9081526001602090815260408083209386168352928152828220878352905290812055612ee683838361220a565b50505050505050565b6060604082511015612f0e57505060408051602081019091525f815290565b5f60208301519050602060408451612f269190615aed565b612f309190615e1c565b811115612f4c57505060408051602081019091525f8152919050565b600181016020026020840101915050919050565b5f81515f03612f7057505f919050565b50602001515f1a90565b612f8381613df9565b612fa25780604051630c89984b60e31b81526004016103169190615e3b565b50565b60605f612fb28484613e27565b9050808015612fd357505f3d1180612fd357505f846001600160a01b03163b115b15612fe857612fe0613e3a565b9150506102b4565b801561301257604051639996b31560e01b81526001600160a01b0385166004820152602401610316565b3d1561302557613020613e53565b61303e565b60405163d6bda27560e01b815260040160405180910390fd5b5092915050565b604080516080810182525f8082526020820181905291810182905260608101919091526130728383613e5e565b825260408201526130838284613e5e565b6020830152606082015292915050565b5f80516020615ff9833981519152546002036130c257604051633ee5aeb560e01b815260040160405180910390fd5b565b5f80851584151781871282861218178584141780156130e95786859250925050611da5565b505f858413156130fd575092949193919260015b8386035f8112604c8213178015613130578215613122575f8994509450505050611da5565b885f94509450505050611da5565b600a82900a8981028a82828161314857613148615e08565b0514613174578415613164575f8b965096505050505050611da5565b8a5f965096505050505050611da5565b8415613189578896509450611da59350505050565b9550879450611da59350505050565b5f805f6131a484613ec7565b909250905060018260038111156131bd576131bd615e4d565b141580156131dc57505f8260038111156131d9576131d9615e4d565b14155b156103bb57838260405163ee07877f60e01b8152600401610316929190615e61565b5f806001600160e01b038416601b0b60e085901d61321d828287613f54565b9350935050505b9250929050565b5f805f805f61323a87876140ba565b9250925092505f8061324c85856140fd565b915091508183801561325b5750815b9650965050505050509250929050565b60605f825167ffffffffffffffff81111561328857613288614e34565b6040519080825280602002602001820160405280156132b1578160200160208202803683370190505b5090505f808451116132c3575f6132c9565b83516001015b85516001010190505f8167ffffffffffffffff8111156132eb576132eb614e34565b60405190808252806020026020018201604052801561331e57816020015b60608152602001906001900390816133095790505b5090505f613342604080516002815233602082015230818301526060810190915290565b828281518110613354576133546156d8565b60200260200101819052505f5b87518110156133b1578180600101925050878181518110613384576133846156d8565b602002602001015183838151811061339e5761339e6156d8565b6020908102919091010152600101613361565b50855115613543578080600101915050838282815181106133d4576133d46156d8565b60200260200101819052505f5b8651811015613541576134908782815181106133ff576133ff6156d8565b60200260200101515f015161346d61343b8a8581518110613422576134226156d8565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b89848151811061347f5761347f6156d8565b6020026020010151604001516141d5565b6134b057604051630a57f30960e31b815260048101829052602401610316565b8681815181106134c2576134c26156d8565b60200260200101515f01516001600160a01b03165f1b8582815181106134ea576134ea6156d8565b6020026020010181815250508180600101925050868181518110613510576135106156d8565b60200260200101516020015183838151811061352e5761352e6156d8565b60209081029190910101526001016133e1565b505b5095945050505050565b5f805f6131a484614245565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f511483166135af5783831516156135a3573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b6040516323b872dd60e01b5f8181526001600160a01b038781166004528616602452604485905291602083606481808c5af1925060015f5114831661361757838315161561360b573d5f823e3d81fd5b5f883b113d1516831692505b604052505f60605295945050505050565b5f8085158415178015613640575f92505f915061373d565b61364a8487615e9a565b91505f613656886142a4565b90505f613662876142a4565b90505f61366f83836142d2565b5090505f6f0785ee10d5da46d900f436a0000000008211156136a4576f0785ee10d5da46d900f436a000000000820491506025015b670de0b6b3a76400008211156136c557670de0b6b3a7640000820491506012015b633b9aca008211156136de57633b9aca00820491506009015b6127108211156136f357612710820491506004015b811561370757600a820491506001016136f3565b6137118187615e9a565b95506137338b8a61372d878761372887600a615f99565b6142ee565b896143ba565b9097509550505050505b5094509492505050565b5f805f61375485856140fd565b9150915080158015613764575081155b1561378c57604051638eba4d0760e01b81526004810186905260248101859052604401610316565b509392505050565b5f806137a0848461445a565b90945092506137b186868686613cfb565b9150915094509492505050565b5f80835f036137ea57604051637a97930f60e01b81526004810187905260248101869052604401610316565b855f036137fb57505f905080611da5565b5f805f806138098a8a6144af565b919b509950915061381a88886144af565b919950975090505f61382b8b6142a4565b90505f6138378a6142a4565b90507f161bcca7119915b50764b4abe86529797775a5f1719510000000000000000000604c81831015613bfc57841561388e57507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b9050604b613bd4565b6f4b3b4ca85a86c47a098a2240000000008310156139ba57678ac7230489e8000083101561391e576402540be4008310156138ec57620186a08310156138dc5750620186a090506005613b95565b506402540be4009050600a613b95565b655af3107a400083101561390b5750655af3107a40009050600e613b95565b50678ac7230489e8000090506013613b95565b6b204fce5e3e250261100000008310156139705769152d02c7e14af6800000831015613959575069152d02c7e14af680000090506017613b95565b506b204fce5e3e250261100000009050601c613b95565b6d314dc6448d9338c15b0a0000000083101561399f57506d314dc6448d9338c15b0a0000000090506021613b95565b506f4b3b4ca85a86c47a098a22400000000090506026613b95565b780197d4df19d605767337e9f14d3eec8920e400000000000000831015613ab25773af298d050e4395d69670b12b7f41000000000000831015613a4d577172cb5bd86321e38cb6ce6682e80000000000831015613a2e57507172cb5bd86321e38cb6ce6682e800000000009050602b613b95565b5073af298d050e4395d69670b12b7f4100000000000090506030613b95565b76010b46c6cdd6e3e0828f4db456ff0c8ea0000000000000831015613a8e575076010b46c6cdd6e3e0828f4db456ff0c8ea000000000000090506035613b95565b50780197d4df19d605767337e9f14d3eec8920e4000000000000009050603a613b95565b7c03b58e88c75313ec9d329eaaa18fb92f75215b17100000000000000000831015613b48577a026e4d30eccc3215dd8f3157d27e23acbdcfe68000000000000000831015613b2057507a026e4d30eccc3215dd8f3157d27e23acbdcfe680000000000000009050603f613b95565b507c03b58e88c75313ec9d329eaaa18fb92f75215b1710000000000000000090506044613b95565b7e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000831015613b9557507e05a8e89d75252446eb5d5d5b1cc5edf20a1a059e10ca000000000000000000905060495b818311613baa57600a820491505f1901613b95565b815f03613bd4576040516305e51ecb60e01b8152600481018d9052602481018c9052604401610316565b85613bfc576040516305e51ecb60e01b8152600481018f9052602481018e9052604401610316565b80600160ff1b018d12613c1357808d039c50613c51565b600160ff1b9c90038c015f811315613c5157806001600160ff1b03038b13613c3e57998a0199613c51565b5f80995099505050505050505050611da5565b5f808e128015613c6057505f8c135b15613c8157600160ff1b8e01808d13613c79575f613c7d565b808d035b9150505b8b818f01039750613c9e8f8e613c988887896142ee565b8b6143ba565b90995097505f811315613ce857604c811315613cc8575f809a509a50505050505050505050611da5565b80600a0a8981613cda57613cda615e08565b059850885f03613ce8575f97505b50969850949650611da595505050505050565b5f8085158415178015613d2757865f03613d1b5784849250925050611da5565b86869250925050611da5565b613d318787614709565b9097509550613d408585614709565b909550935085841315613d54579395929492935b838603604c811115613d6d578787935093505050611da5565b80600a0a8681613d7f57613d7f615e08565b0595505086850180881860ff90811c151589881890911c15168015613de857876001600160ff1b0303613dcf5760405163d556b11160e01b8152600481018a905260248101899052604401610316565b600a968790059690980586019760019790970196613dec565b8198505b5096979596505050505050565b5f600882511015613e0b57505f919050565b506008015167ffffffffffffffff1667ff0a89c674ee78741490565b5f805f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f80613e7b8460600151856040015161281e90919063ffffffff16565b915083604001519050613e9b836040015183611b4c90919063ffffffff16565b156132245782604001519150613ebe84606001518361289b90919063ffffffff16565b90509250929050565b5f80613ed1614752565b60405163b7bad1b160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb93899063b7bad1b19060240160408051808303815f875af1158015613f27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f4b9190615fa4565b91509150915091565b5f805f851215613f8157604051634a7d166b60e01b81526004810186905260248101859052604401610316565b845f03613f9357505f90506001611cb6565b8460ff8416850185811215613fc55760405163d556b11160e01b81526004810188905260248101879052604401610316565b5f805f83121561401157604c19831215613fe8575f809550955050505050611cb6565b825f03600a0a9150818481613fff57613fff615e08565b0495505084029091149150611cb69050565b5f8313156140aa57604d83131561404e5760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b82600a0a9150815f198161406457614064615e08565b048411156140985760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610316565b5091909102925060019150611cb69050565b8360019550955050505050611cb6565b5f808060ff841681036001600160ff1b038611156140ec57600a860460018201600a88065f14935093509350506140f6565b8593509150600190505b9250925092565b5f601b83900b8314838382614161577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e100000000000000000086051561414157620186a0860595506005850194505b8586601b0b1461415c57600a86059550846001019450614141565b614177565b855f0361417757505f9250600191506132249050565b848560030b146141ba575f85121561419757505f92508291506132249050565b60405163d556b11160e01b81526004810183905260248101829052604401610316565b50506001600160e01b03841660e084901b1791509250929050565b5f836001600160a01b03163b5f03614233575f806141f385856147dd565b5090925090505f81600381111561420c5761420c615e4d565b14801561422a5750856001600160a01b0316826001600160a01b0316145b925050506103bb565b61423e848484614823565b90506103bb565b5f8061424f614752565b604051630782d7e160e01b81526001600160a01b038416600482015273200e12d10bb0c5e4a17e7018f0f1161919bb938990630782d7e1906024016040805180830381865afa158015613f27573d5f803e3d5ffd5b5f808212156142c957600160ff1b82036142c35750600160ff1b919050565b505f0390565b5090565b919050565b5f805f1983850993909202808410938190039390930393915050565b5f805f6142fb86866142d2565b91509150815f0361431f5783818161431557614315615e08565b04925050506103bb565b8382106143505760405163362ced0960e11b8152600481018790526024810186905260448101859052606401610316565b5f84868809600186198101871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103025f82900382900490920185841190960395909502919093039390930492909217029150509392505050565b5f805f8587181215614436576001600160ff1b03841115614423576143e76001600160ff1b03600161567f565b84036143fb5750600160ff1b905081611da5565b614406600a85615e1c565b61440f90615fe4565b61441a846001615e9a565b91509150611da5565b61442c84615fe4565b8391509150611da5565b6001600160ff1b038411156144505761440f600a85615e1c565b5082905081611da5565b5f80600160ff1b84036144a5576001600160ff1b0383036144985760405163d556b11160e01b81526004810185905260248101849052604401610316565b600a840593508260010192505b50505f9190910391565b5f805f845f036144c757505f915081905060016140f6565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85055f036146b4576f4b3b4ca85a86c47a098a224000000000850515801561452957507f80000000000000000000000000000000000000000000000000000000000000268412155b1561454a576f4b3b4ca85a86c47a098a224000000000850294506026840393505b7728c87cb5c89a2571ebfdcb54864ada834a00000000000000850515801561459257507f80000000000000000000000000000000000000000000000000000000000000138412155b156145ab57678ac7230489e80000850294506013840393505b7b097edd871cfda3a5697758bf0e3cbb5ac5741c64000000000000000085051580156145f757507f800000000000000000000000000000000000000000000000000000000000000a8412155b1561460d576402540be40085029450600a840393505b7e3899162693736ac531a5a58f1fbb4b746504382ca7e4000000000000000000850515801561465c57507f80000000000000000000000000000000000000000000000000000000000000028412155b156146725760648502945060028403935061460d565b7546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b85051580156146a257506001600160ff1b018412155b156146b457600a850294506001840393505b600a808602908105861480156146d157506001600160ff1b018512155b156146e0578095506001850394505b50939492935050507546bf5bb0385045767e0f0ef2e7aa1e517e454637d1dd604b1b8305151590565b5f805f805f61471887876144af565b92509250925080614746576040516305e51ecb60e01b81526004810188905260248101879052604401610316565b50909590945092505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b15806147a9575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b156130c2576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610316565b5f805f8351604103614814576020840151604085015160608601515f1a61480688828585614874565b9550955095505050506140f6565b505081515f91506002906140f6565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156148ad57505f91506003905082614932565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156148fe573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661492957505f925060019150829050614932565b92505f91508190505b9450945094915050565b604051806080016040528061494f614968565b81526020015f81526020015f8152602001606081525090565b6040518060a001604052805f6001600160a01b031681526020016149b660405180606001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081525090565b8152606060208201819052604082018190525f91015290565b6040518060e001604052806149e2614968565b81526020015f81526020015f80191681526020015f8019168152602001606081526020015f8152602001606081525090565b5f60208284031215614a24575f80fd5b81356001600160e01b0319811681146103bb575f80fd5b5f8083601f840112614a4b575f80fd5b50813567ffffffffffffffff811115614a62575f80fd5b6020830191508360208260051b8501011115613224575f80fd5b5f805f60408486031215614a8e575f80fd5b833567ffffffffffffffff80821115614aa5575f80fd5b9085019060a08288031215614ab8575f80fd5b90935060208501359080821115614acd575f80fd5b50614ada86828701614a3b565b9497909650939450505050565b5f60208284031215614af7575f80fd5b5035919050565b6001600160a01b0381168114612fa2575f80fd5b80356142cd81614afe565b5f805f805f60808688031215614b31575f80fd5b8535614b3c81614afe565b94506020860135935060408601359250606086013567ffffffffffffffff811115614b65575f80fd5b614b7188828901614a3b565b969995985093965092949392505050565b5f805f60608486031215614b94575f80fd5b8335614b9f81614afe565b92506020840135614baf81614afe565b929592945050506040919091013590565b5f805f805f60808688031215614bd4575f80fd5b8535614bdf81614afe565b94506020860135614bef81614afe565b935060408601359250606086013567ffffffffffffffff80821115614c12575f80fd5b818801915088601f830112614c25575f80fd5b813581811115614c33575f80fd5b896020828501011115614c44575f80fd5b9699959850939650602001949392505050565b5f60208284031215614c67575f80fd5b81356103bb81614afe565b5f60c08284031215614c82575f80fd5b50919050565b5f60208284031215614c98575f80fd5b813567ffffffffffffffff811115614cae575f80fd5b61052d84828501614c72565b5f805f60408486031215614ccc575f80fd5b833567ffffffffffffffff80821115614ce3575f80fd5b614cef87838801614c72565b94506020860135915080821115614acd575f80fd5b5f60208284031215614d14575f80fd5b813567ffffffffffffffff811115614d2a575f80fd5b8201608081850312156103bb575f80fd5b5f8060208385031215614d4c575f80fd5b823567ffffffffffffffff811115614d62575f80fd5b614d6e85828601614a3b565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614dfd57603f19888603018452614deb858351614d7a565b94509285019290850190600101614dcf565b5092979650505050505050565b5f8060408385031215614e1b575f80fd5b8235614e2681614afe565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b60405290565b6040805190810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b60405160a0810167ffffffffffffffff81118282101715614e6b57614e6b614e34565b604051601f8201601f1916810167ffffffffffffffff81118282101715614ee057614ee0614e34565b604052919050565b5f82601f830112614ef7575f80fd5b813567ffffffffffffffff811115614f1157614f11614e34565b614f24601f8201601f1916602001614eb7565b818152846020838601011115614f38575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608284031215614f64575f80fd5b614f6c614e48565b90508135614f7981614afe565b81526020820135614f8981614afe565b6020820152604082013567ffffffffffffffff811115614fa7575f80fd5b614fb384828501614ee8565b60408301525092915050565b5f67ffffffffffffffff821115614fd857614fd8614e34565b5060051b60200190565b5f60408284031215614ff2575f80fd5b614ffa614e71565b9050813561500781614afe565b808252506020820135602082015292915050565b5f82601f83011261502a575f80fd5b8135602061503f61503a83614fbf565b614eb7565b8083825260208201915060208460061b870101935086841115615060575f80fd5b602086015b84811015615085576150778882614fe2565b835291830191604001615065565b509695505050505050565b5f60a082840312156150a0575f80fd5b6150a8614e94565b90506150b382614b12565b8152602082013567ffffffffffffffff808211156150cf575f80fd5b6150db85838601614f54565b602084015260408401359150808211156150f3575f80fd5b6150ff8583860161501b565b60408401526060840135915080821115615117575f80fd5b506151248482850161501b565b6060830152506080820135608082015292915050565b5f61514761503a84614fbf565b8381529050602080820190600585811b850187811115615165575f80fd5b855b8181101561525257803567ffffffffffffffff80821115615186575f80fd5b908801906060828c031215615199575f80fd5b6151a1614e48565b82356151ac81614afe565b815282870135828111156151be575f80fd5b8301601f81018d136151ce575f80fd5b80356151dc61503a82614fbf565b81815290881b8201890190898101908f8311156151f7575f80fd5b928a01925b828410156152155783358252928a0192908a01906151fc565b848b0152506040915050838101358381111561522f575f80fd5b61523b8e828701614ee8565b918301919091525087525050938301938301615167565b50505050509392505050565b5f82601f83011261526d575f80fd5b6103bb8383356020850161513a565b5f805f805f6101408688031215615291575f80fd5b853567ffffffffffffffff808211156152a8575f80fd5b6152b489838a01615090565b965060208801359150808211156152c9575f80fd5b6152d589838a01615090565b95506152e48960408a01614c72565b94506101008801359150808211156152fa575f80fd5b61530689838a0161525e565b935061012088013591508082111561531c575f80fd5b506153298882890161525e565b9150509295509295909350565b5f6102b43683615090565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f813561537581614afe565b6001600160a01b03908116845260208301359061539182614afe565b166020840152604082013536839003601e190181126153ae575f80fd5b820160208101903567ffffffffffffffff8111156153ca575f80fd5b8036038213156153d8575f80fd5b606060408601526153ed606086018284615341565b95945050505050565b5f808335601e1984360301811261540b575f80fd5b830160208101925035905067ffffffffffffffff81111561542a575f80fd5b8060061b3603821315613224575f80fd5b8183525f60208085019450825f5b8581101561548157813561545c81614afe565b6001600160a01b03168752818301358388015260409687019690910190600101615449565b509495945050505050565b5f6001600160a01b0380861683528460208401526060604084015283356154b281614afe565b166060830152602083013536849003605e190181126154cf575f80fd5b60a060808401526154e66101008401858301615369565b90506154f560408501856153f6565b605f19808685030160a087015261550d84838561543b565b935061551c60608801886153f6565b93509150808685030160c08701525061553683838361543b565b92505050608084013560e084015280915050949350505050565b5f61555d61503a84614fbf565b80848252602080830192508560051b85013681111561557a575f80fd5b855b8181101561560457803567ffffffffffffffff8082111561559b575f80fd5b8189019150604082360312156155af575f80fd5b6155b7614e71565b8235828111156155c5575f80fd5b6155d136828601614f54565b82525085830135828111156155e4575f80fd5b6155f03682860161525e565b82880152508752505093820193820161557c565b50919695505050505050565b5f6001600160a01b03808916835280881660208401525085604083015284606083015260a0608083015261564860a083018486615341565b98975050505050505050565b5f60208284031215615664575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156102b4576102b461566b565b5f808335601e198436030181126156a7575f80fd5b83018035915067ffffffffffffffff8211156156c1575f80fd5b6020019150600581901b3603821315613224575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112615700575f80fd5b9190910192915050565b5f8235609e19833603018112615700575f80fd5b5f808335601e19843603018112615733575f80fd5b83018035915067ffffffffffffffff82111561574d575f80fd5b6020019150600681901b3603821315613224575f80fd5b5f60808236031215615774575f80fd5b6040516080810167ffffffffffffffff828210818311171561579857615798614e34565b8160405284359150808211156157ac575f80fd5b6157b836838701615090565b8352602085013560208401526040850135604084015260608501359150808211156157e1575f80fd5b506157ee3682860161525e565b60608301525092915050565b5f6020828403121561580a575f80fd5b813580151581146103bb575f80fd5b5f815180845260208085019450602084015f5b8381101561548157815180516001600160a01b03168852830151838801526040909601959082019060010161582c565b5f6001600160a01b03808351168452602083015160a060208601528181511660a08601528160208201511660c08601526040810151915050606060e08501526158a9610100850182614d7a565b9050604083015184820360408601526158c28282615819565b915050606083015184820360608601526158dc8282615819565b915050608083015160808501528091505092915050565b5f815180845260208085019450602084015f5b8381101561548157815187529582019590820190600101615906565b5f6001600160a01b0380871683526020608081850152865160808086015261594e61010086018261585c565b90508188015160a086015260408089015160c08701526060808a0151607f198885030160e08901528381518086528686019150868160051b87010187840193505f5b828110156159ea57601f1988830301845284518a815116835289810151878b8501526159be888501826158f3565b91890151848303858b01529190506159d68183614d7a565b968b0196958b019593505050600101615990565b5080995050505050505050505083604083015282606083015295945050505050565b5f808335601e19843603018112615a21575f80fd5b83018035915067ffffffffffffffff821115615a3b575f80fd5b602001915036819003821315613224575f80fd5b5f8235605e19833603018112615700575f80fd5b5f6102b43683614f54565b5f60408284031215615a7e575f80fd5b6103bb8383614fe2565b6001600160a01b0384168152826020820152606060408201525f6153ed606083018461585c565b6001600160a01b0385168152836020820152606060408201525f615ad7606083018486615341565b9695505050505050565b5f6103bb36848461513a565b818103818111156102b4576102b461566b565b828482375f8382015f815283518060208601835e5f910190815295945050505050565b5f6101206001600160a01b0387168352806020840152615b458184018761585c565b90508281036040840152615b59818661585c565b9150508235606083015260208301356080830152604083013560a0830152606083013560c0830152608083013560e083015260a083013561010083015295945050505050565b602081525f6103bb602083018461585c565b5f60018201615bc257615bc261566b565b5060010190565b5f8282518085526020808601955060208260051b840101602086015f5b84811015615c1457601f19868403018952615c028383516158f3565b98840198925090830190600101615be6565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e06060840152615c5a610100840182614d7a565b9050606084015160808401526080840151601f19808584030160a0860152615c828383615bc9565b925060a08601519150808584030160c0860152615c9f83836158f3565b925060c08601519150808584030160e0860152506153ed82826158f3565b5f82601f830112615ccc575f80fd5b81516020615cdc61503a83614fbf565b8083825260208201915060208460051b870101935086841115615cfd575f80fd5b602086015b848110156150855780518352918301918301615d02565b5f8060408385031215615d2a575f80fd5b825167ffffffffffffffff80821115615d41575f80fd5b818501915085601f830112615d54575f80fd5b81516020615d6461503a83614fbf565b82815260059290921b84018101918181019089841115615d82575f80fd5b948201945b83861015615da057855182529482019490820190615d87565b91880151919650909350505080821115615db8575f80fd5b50615dc585828601615cbd565b9150509250929050565b828152604060208201525f61052d60408301846158f3565b6001600160a01b0383168152604060208201525f61052d6040830184615bc9565b634e487b7160e01b5f52601260045260245ffd5b5f82615e3657634e487b7160e01b5f52601260045260245ffd5b500490565b602081525f6103bb6020830184614d7a565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040810160048310615e8d57634e487b7160e01b5f52602160045260245ffd5b8260208301529392505050565b8082018281125f8312801582168215821617156114ac576114ac61566b565b600181815b80851115615ef357815f1904821115615ed957615ed961566b565b80851615615ee657918102915b93841c9390800290615ebe565b509250929050565b5f82615f09575060016102b4565b81615f1557505f6102b4565b8160018114615f2b5760028114615f3557615f51565b60019150506102b4565b60ff841115615f4657615f4661566b565b50506001821b6102b4565b5060208310610133831016604e8410600b8410161715615f74575081810a6102b4565b615f7e8383615eb9565b805f1904821115615f9157615f9161566b565b029392505050565b5f6103bb8383615efb565b5f8060408385031215615fb5575f80fd5b825160048110615fc3575f80fd5b602084015190925060ff81168114615fd9575f80fd5b809150509250929050565b5f600160ff1b82016142c3576142c361566b56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00"; diff --git a/src/generated/RouteProcessorRaindexV6ArbOrderTaker.pointers.sol b/src/generated/RouteProcessorRaindexV6ArbOrderTaker.pointers.sol index ff62d82305..2a49bd9c5e 100644 --- a/src/generated/RouteProcessorRaindexV6ArbOrderTaker.pointers.sol +++ b/src/generated/RouteProcessorRaindexV6ArbOrderTaker.pointers.sol @@ -10,12 +10,12 @@ pragma solidity ^0.8.25; // file needs the contract to exist so that it can be compiled. /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0xc3fb3bb0355fee22e54cade57f5ff828478d59f34fdd8057bc0bc6a11b3d48fc); +bytes32 constant BYTECODE_HASH = bytes32(0xebca76aecd91efeee0840b70028dda00c90b06266c1bea04d5367a58d5e7f751); /// @dev The deterministic deploy address of the contract when deployed via /// the Zoltu factory. -address constant DEPLOYED_ADDRESS = address(0x5Ec2625ee7c73c85fAb2bc4cf527E1434F0dcC5d); +address constant DEPLOYED_ADDRESS = address(0xDd436bd0e92389e1c45E6Af5F0C2D989c626d49e); /// @dev The runtime bytecode of the contract. bytes constant RUNTIME_CODE = - hex"608060405260043610610034575f3560e01c806301ffc9a71461003d578063691f9ed714610070578063b17c83c11461008f57005b3661003b57005b005b348015610048575f80fd5b5061005c610057366004611458565b6100a2565b604051901515815260200160405180910390f35b34801561007b575f80fd5b5061003b61008a366004611493565b6100f3565b61003b61009d366004611535565b610200565b5f6001600160e01b0319821663691f9ed760e01b14806100d257506001600160e01b0319821663b17c83c160e01b145b806100ed57506301ffc9a760e01b6001600160e01b03198316145b92915050565b736e2d0e71d900474b262e545bc4c98b71ab368d2161011d6001600160a01b038816825f196104c2565b5f61012a838501856116b0565b90505f61013f8761013a8b61053c565b6105c0565b5090505f806101518861013a8c61053c565b91509150806101685781610164816116ea565b9250505b604051632646478b60e01b81526001600160a01b03861690632646478b9061019e908e9087908f90889030908c9060040161173c565b6020604051808303815f875af11580156101ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101de9190611787565b506101f36001600160a01b038c16865f6104c2565b5050505050505050505050565b610208610602565b6102176102148261190a565b50565b61022460808301836119c6565b90505f0361024557604051639c95219f60e01b815260040160405180910390fd5b6001600160a01b0383167386594ac4319230870c6e587f4aca48fab575619e146102925760405163516e822d60e01b81526001600160a01b03841660048201526024015b60405180910390fd5b5f6102a060808401846119c6565b5f8181106102b0576102b0611a0c565b90506020028101906102c29190611a20565b6102cc9080611a3e565b6102da906040810190611a52565b6102e760808601866119c6565b5f8181106102f7576102f7611a0c565b90506020028101906103099190611a20565b6020013581811061031c5761031c611a0c565b6103329260206040909202019081019150611a98565b90505f61034260808501856119c6565b5f81811061035257610352611a0c565b90506020028101906103649190611a20565b61036e9080611a3e565b61037c906060810190611a52565b61038960808701876119c6565b5f81811061039957610399611a0c565b90506020028101906103ab9190611a20565b604001358181106103be576103be611a0c565b6103d49260206040909202019081019150611a98565b90506103eb6001600160a01b038316865f196104c2565b6040516334e3942b60e11b81526001600160a01b038616906369c7285690610417908790600401611cfc565b60408051808303815f875af1158015610432573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104569190611efc565b5061046d90506001600160a01b038316865f6104c2565b6104926104798461190a565b836104838561053c565b8461048d8661053c565b610630565b50506104bd60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050565b6104ce8383835f6108cf565b6104bd576104df83835f60016108cf565b61050757604051635274afe760e01b81526001600160a01b0384166004820152602401610289565b61051483838360016108cf565b6104bd57604051635274afe760e01b81526001600160a01b0384166004820152602401610289565b5f610545610931565b6040516354636d2b60e01b81526001600160a01b038316600482015273200e12d10bb0c5e4a17e7018f0f1161919bb9389906354636d2b906024016020604051808303815f875af115801561059c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100ed9190611f1e565b5f807bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8416601b0b60e085901d6105f48282876109be565b9350935050505b9250929050565b61060a610b27565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6040805160018082528183019092525f91816020015b6060815260200190600190039081610646575050604080516003808252608082019092529192505f919060208201606080368337019050506040516370a0823160e01b81523060048201529091505f906001600160a01b038816906370a0823190602401602060405180830381865afa1580156106c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106e99190611787565b90508015610705576107056001600160a01b0388163383610b69565b5f6107108288610b76565b50905080835f8151811061072657610726611a0c565b602090810291909101015250506040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610777573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061079b9190611787565b905080156107b7576107b76001600160a01b0386163383610b69565b5f6107c28286610b76565b50905080836001815181106107d9576107d9611a0c565b60209081029190910101525047905080156107f8576107f83382610bb6565b5f610804826012610b76565b509050808360028151811061081b5761081b611a0c565b602002602001018181525050505080825f8151811061083c5761083c611a0c565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160a0810182525f918101828152606080830193909352608082018390528152602081019190915281526020019060019003908161085d57905050905087815f815181106108b0576108b0611a0c565b60200260200101819052506108c58382610c2d565b5050505050505050565b60405163095ea7b360e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610925578383151615610919573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b1580610988575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b156109bc576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610289565b565b5f805f8512156109eb57604051634a7d166b60e01b81526004810186905260248101859052604401610289565b845f036109fd57505f90506001610b1f565b8460ff8416850185811215610a2f5760405163d556b11160e01b81526004810188905260248101879052604401610289565b5f805f831215610a7b57604c19831215610a52575f809550955050505050610b1f565b825f03600a0a9150818481610a6957610a69611f3e565b0495505084029091149150610b1f9050565b5f831315610b1457604d831315610ab85760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610289565b82600a0a9150815f1981610ace57610ace611f3e565b04841115610b025760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610289565b5091909102925060019150610b1f9050565b509193506001925050505b935093915050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00546002036109bc57604051633ee5aeb560e01b815260040160405180910390fd5b6105148383836001610df1565b5f805f805f610b858787610e3b565b9250925092505f80610b978585610e97565b9150915081838015610ba65750815b9650965050505050509250929050565b80471015610be05760405163cf47918160e01b815247600482015260248101829052604401610289565b610bf9828260405180602001604052805f815250610f84565b15610c02575050565b3d15610c1457610c10610f99565b5050565b60405163d6bda27560e01b815260040160405180910390fd5b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b86518110156108c557868181518110610c9457610c94611a0c565b602002602001015193505f845f015160400151511115610de9575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001610d0c8d8a60200151610fa4565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401610d379190611fd9565b5f60405180830381865afa158015610d51573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d7891908101906120da565b9150505f81511115610de75784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490610db9908a908590600401612190565b5f604051808303815f87803b158015610dd0575f80fd5b505af1158015610de2573d5f803e3d5ffd5b505050505b505b600101610c79565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610925578383151615610919573d5f823e3d81fd5b5f808060ff841681037f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff861115610e8657600a860460018201600a88065f1493509350935050610e90565b8593509150600190505b9250925092565b5f601b83900b8314838382610efb577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e1000000000000000000860515610edb57620186a0860595506005850194505b8586601b0b14610ef657600a86059550846001019450610edb565b610f11565b855f03610f1157505f9250600191506105fb9050565b848560030b14610f54575f851215610f3157505f92508291506105fb9050565b60405163d556b11160e01b81526004810183905260248101829052604401610289565b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841660e084901b1791509250929050565b5f805f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b60605f825167ffffffffffffffff811115610fc157610fc16115b3565b604051908082528060200260200182016040528015610fea578160200160208202803683370190505b5090505f80845111610ffc575f611002565b83516001015b85516001010190505f8167ffffffffffffffff811115611024576110246115b3565b60405190808252806020026020018201604052801561105757816020015b60608152602001906001900390816110425790505b5090505f61107b604080516002815233602082015230818301526060810190915290565b82828151811061108d5761108d611a0c565b60200260200101819052505f5b87518110156110ea5781806001019250508781815181106110bd576110bd611a0c565b60200260200101518383815181106110d7576110d7611a0c565b602090810291909101015260010161109a565b5085511561127c5780806001019150508382828151811061110d5761110d611a0c565b60200260200101819052505f5b865181101561127a576111c987828151811061113857611138611a0c565b60200260200101515f01516111a66111748a858151811061115b5761115b611a0c565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b8984815181106111b8576111b8611a0c565b602002602001015160400151611286565b6111e957604051630a57f30960e31b815260048101829052602401610289565b8681815181106111fb576111fb611a0c565b60200260200101515f01516001600160a01b03165f1b85828151811061122357611223611a0c565b602002602001018181525050818060010192505086818151811061124957611249611a0c565b60200260200101516020015183838151811061126757611267611a0c565b602090810291909101015260010161111a565b505b5095945050505050565b5f836001600160a01b03163b5f036112e4575f806112a485856112f9565b5090925090505f8160038111156112bd576112bd6121a8565b1480156112db5750856001600160a01b0316826001600160a01b0316145b925050506112f2565b6112ef84848461133f565b90505b9392505050565b5f805f8351604103611330576020840151604085015160608601515f1a61132288828585611390565b955095509550505050610e90565b505081515f9150600290610e90565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156113c957505f9150600390508261144e565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561141a573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661144557505f92506001915082905061144e565b92505f91508190505b9450945094915050565b5f60208284031215611468575f80fd5b81356001600160e01b0319811681146112f2575f80fd5b6001600160a01b0381168114610214575f80fd5b5f805f805f8060a087890312156114a8575f80fd5b86356114b38161147f565b955060208701356114c38161147f565b94506040870135935060608701359250608087013567ffffffffffffffff808211156114ed575f80fd5b818901915089601f830112611500575f80fd5b81358181111561150e575f80fd5b8a602082850101111561151f575f80fd5b6020830194508093505050509295509295509295565b5f805f60608486031215611547575f80fd5b83356115528161147f565b9250602084013567ffffffffffffffff8082111561156e575f80fd5b9085019060c08288031215611581575f80fd5b90925060408501359080821115611596575f80fd5b508401604081870312156115a8575f80fd5b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156115ea576115ea6115b3565b60405290565b6040805190810167ffffffffffffffff811182821017156115ea576115ea6115b3565b604051601f8201601f1916810167ffffffffffffffff8111828210171561163c5761163c6115b3565b604052919050565b5f82601f830112611653575f80fd5b813567ffffffffffffffff81111561166d5761166d6115b3565b611680601f8201601f1916602001611613565b818152846020838601011115611694575f80fd5b816020850160208301375f918101602001919091529392505050565b5f602082840312156116c0575f80fd5b813567ffffffffffffffff8111156116d6575f80fd5b6116e284828501611644565b949350505050565b5f6001820161170757634e487b7160e01b5f52601160045260245ffd5b5060010190565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f6001600160a01b038089168352876020840152808716604084015285606084015280851660808401525060c060a083015261177b60c083018461170e565b98975050505050505050565b5f60208284031215611797575f80fd5b5051919050565b5f67ffffffffffffffff8211156117b7576117b76115b3565b5060051b60200190565b5f82601f8301126117d0575f80fd5b813560206117e56117e08361179e565b611613565b82815260059290921b84018101918181019086841115611803575f80fd5b8286015b848110156118ff57803567ffffffffffffffff80821115611826575f80fd5b908801906060828b03601f1901121561183d575f80fd5b6118456115c7565b868301356118528161147f565b815260408381013583811115611866575f80fd5b8401603f81018d13611876575f80fd5b888101356118866117e08261179e565b81815260059190911b82018301908a8101908f8311156118a4575f80fd5b928401925b828410156118c25783358252928b0192908b01906118a9565b858c01525050506060840135838111156118da575f80fd5b6118e88d8a83880101611644565b918301919091525085525050918301918301611807565b509695505050505050565b5f6040823603121561191a575f80fd5b6119226115f0565b823567ffffffffffffffff80821115611939575f80fd5b81850191506060823603121561194d575f80fd5b6119556115c7565b82356119608161147f565b815260208301356119708161147f565b6020820152604083013582811115611986575f80fd5b61199236828601611644565b604083015250835260208501359150808211156119ad575f80fd5b506119ba368286016117c1565b60208301525092915050565b5f808335601e198436030181126119db575f80fd5b83018035915067ffffffffffffffff8211156119f5575f80fd5b6020019150600581901b36038213156105fb575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112611a34575f80fd5b9190910192915050565b5f8235609e19833603018112611a34575f80fd5b5f808335601e19843603018112611a67575f80fd5b83018035915067ffffffffffffffff821115611a81575f80fd5b6020019150600681901b36038213156105fb575f80fd5b5f60208284031215611aa8575f80fd5b81356112f28161147f565b5f808335601e19843603018112611ac8575f80fd5b830160208101925035905067ffffffffffffffff811115611ae7575f80fd5b8060051b36038213156105fb575f80fd5b5f8235605e19833603018112611b0c575f80fd5b90910192915050565b5f808335601e19843603018112611b2a575f80fd5b830160208101925035905067ffffffffffffffff811115611b49575f80fd5b8036038213156105fb575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f808335601e19843603018112611b94575f80fd5b830160208101925035905067ffffffffffffffff811115611bb3575f80fd5b8060061b36038213156105fb575f80fd5b8183525f60208085019450825f5b85811015611c0a578135611be58161147f565b6001600160a01b03168752818301358388015260409687019690910190600101611bd2565b509495945050505050565b8183526020808401935f91600585811b8301820185855b88811015611cee57858303601f19018a52611c478289611af8565b60608135611c548161147f565b6001600160a01b03168552611c6b82880183611ab3565b82898801528083880152608092507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115611ca5575f80fd5b871b808288850137860190506040611cbf84820185611b15565b9450838884030182890152611cd78484018683611b57565b9e8a019e9750505093870193505050600101611c2c565b509098975050505050505050565b5f602080835260e08301843582850152604082860135818601526060818701358187015280870135801515808214611d32575f80fd5b8060808901525050611d476080880188611ab3565b60c060a08901529384905261010093848801600582901b89018601835f5b84811015611ec3578b830360ff19018452813536879003607e19018112611d8a575f80fd5b8601803536829003609e19018112611da0575f80fd5b6080855281018035611db18161147f565b6001600160a01b038082166080880152611dcd8e840184611af8565b915060a0808801528135611de08161147f565b8116610120880152818e0135611df58161147f565b16610140870152611e08818c0182611b15565b91508a610160880152611e2061018088018383611b57565b915050611e2f8b830183611b7f565b607f19808985030160c08a0152611e47848385611bc4565b9350611e558d860186611b7f565b93509150808985030160e08a015250611e6f838383611bc4565b9250505060808201358c8701528c8301358d8701528a8301358b870152611e988a840184611ab3565b935091508581038a870152611eae818484611c15565b968d019695505050918a019150600101611d65565b5050611ed260a08c018c611b15565b8b8303601f190160c08d015298509650611eed818989611b57565b9b9a5050505050505050505050565b5f8060408385031215611f0d575f80fd5b505080516020909101519092909150565b5f60208284031215611f2e575f80fd5b815160ff811681146112f2575f80fd5b634e487b7160e01b5f52601260045260245ffd5b5f815180845260208085019450602084015f5b83811015611c0a57815187529582019590820190600101611f65565b5f8282518085526020808601955060208260051b840101602086015f5b84811015611fcc57601f19868403018952611fba838351611f52565b98840198925090830190600101611f9e565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e0606084015261201261010084018261170e565b9050606084015160808401526080840151601f19808584030160a086015261203a8383611f81565b925060a08601519150808584030160c08601526120578383611f52565b925060c08601519150808584030160e0860152506120758282611f52565b95945050505050565b5f82601f83011261208d575f80fd5b8151602061209d6117e08361179e565b8083825260208201915060208460051b8701019350868411156120be575f80fd5b602086015b848110156118ff57805183529183019183016120c3565b5f80604083850312156120eb575f80fd5b825167ffffffffffffffff80821115612102575f80fd5b818501915085601f830112612115575f80fd5b815160206121256117e08361179e565b82815260059290921b84018101918181019089841115612143575f80fd5b948201945b8386101561216157855182529482019490820190612148565b91880151919650909350505080821115612179575f80fd5b506121868582860161207e565b9150509250929050565b828152604060208201525f6116e26040830184611f52565b634e487b7160e01b5f52602160045260245ffd"; + hex"608060405260043610610034575f3560e01c806301ffc9a71461003d578063691f9ed714610070578063b17c83c11461008f57005b3661003b57005b005b348015610048575f80fd5b5061005c610057366004611458565b6100a2565b604051901515815260200160405180910390f35b34801561007b575f80fd5b5061003b61008a366004611493565b6100f3565b61003b61009d366004611535565b610200565b5f6001600160e01b0319821663691f9ed760e01b14806100d257506001600160e01b0319821663b17c83c160e01b145b806100ed57506301ffc9a760e01b6001600160e01b03198316145b92915050565b736e2d0e71d900474b262e545bc4c98b71ab368d2161011d6001600160a01b038816825f196104c2565b5f61012a838501856116b0565b90505f61013f8761013a8b61053c565b6105c0565b5090505f806101518861013a8c61053c565b91509150806101685781610164816116ea565b9250505b604051632646478b60e01b81526001600160a01b03861690632646478b9061019e908e9087908f90889030908c9060040161173c565b6020604051808303815f875af11580156101ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101de9190611787565b506101f36001600160a01b038c16865f6104c2565b5050505050505050505050565b610208610602565b6102176102148261190a565b50565b61022460808301836119c6565b90505f0361024557604051639c95219f60e01b815260040160405180910390fd5b6001600160a01b0383167366f51a9c29480491c9282d99cf324e9f419a4e1d146102925760405163516e822d60e01b81526001600160a01b03841660048201526024015b60405180910390fd5b5f6102a060808401846119c6565b5f8181106102b0576102b0611a0c565b90506020028101906102c29190611a20565b6102cc9080611a3e565b6102da906040810190611a52565b6102e760808601866119c6565b5f8181106102f7576102f7611a0c565b90506020028101906103099190611a20565b6020013581811061031c5761031c611a0c565b6103329260206040909202019081019150611a98565b90505f61034260808501856119c6565b5f81811061035257610352611a0c565b90506020028101906103649190611a20565b61036e9080611a3e565b61037c906060810190611a52565b61038960808701876119c6565b5f81811061039957610399611a0c565b90506020028101906103ab9190611a20565b604001358181106103be576103be611a0c565b6103d49260206040909202019081019150611a98565b90506103eb6001600160a01b038316865f196104c2565b6040516334e3942b60e11b81526001600160a01b038616906369c7285690610417908790600401611cfc565b60408051808303815f875af1158015610432573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104569190611efc565b5061046d90506001600160a01b038316865f6104c2565b6104926104798461190a565b836104838561053c565b8461048d8661053c565b610630565b50506104bd60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b505050565b6104ce8383835f6108cf565b6104bd576104df83835f60016108cf565b61050757604051635274afe760e01b81526001600160a01b0384166004820152602401610289565b61051483838360016108cf565b6104bd57604051635274afe760e01b81526001600160a01b0384166004820152602401610289565b5f610545610931565b6040516354636d2b60e01b81526001600160a01b038316600482015273200e12d10bb0c5e4a17e7018f0f1161919bb9389906354636d2b906024016020604051808303815f875af115801561059c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100ed9190611f1e565b5f807bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8416601b0b60e085901d6105f48282876109be565b9350935050505b9250929050565b61060a610b27565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6040805160018082528183019092525f91816020015b6060815260200190600190039081610646575050604080516003808252608082019092529192505f919060208201606080368337019050506040516370a0823160e01b81523060048201529091505f906001600160a01b038816906370a0823190602401602060405180830381865afa1580156106c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106e99190611787565b90508015610705576107056001600160a01b0388163383610b69565b5f6107108288610b76565b50905080835f8151811061072657610726611a0c565b602090810291909101015250506040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610777573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061079b9190611787565b905080156107b7576107b76001600160a01b0386163383610b69565b5f6107c28286610b76565b50905080836001815181106107d9576107d9611a0c565b60209081029190910101525047905080156107f8576107f83382610bb6565b5f610804826012610b76565b509050808360028151811061081b5761081b611a0c565b602002602001018181525050505080825f8151811061083c5761083c611a0c565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160a0810182525f918101828152606080830193909352608082018390528152602081019190915281526020019060019003908161085d57905050905087815f815181106108b0576108b0611a0c565b60200260200101819052506108c58382610c2d565b5050505050505050565b60405163095ea7b360e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610925578383151615610919573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b73200e12d10bb0c5e4a17e7018f0f1161919bb93893b1580610988575073200e12d10bb0c5e4a17e7018f0f1161919bb93893f7f1de7d717526cba131d684e312dedbf0852adef9cced9e36798ae4937f7145d4114155b156109bc576040516373e6d7b360e01b815273200e12d10bb0c5e4a17e7018f0f1161919bb93896004820152602401610289565b565b5f805f8512156109eb57604051634a7d166b60e01b81526004810186905260248101859052604401610289565b845f036109fd57505f90506001610b1f565b8460ff8416850185811215610a2f5760405163d556b11160e01b81526004810188905260248101879052604401610289565b5f805f831215610a7b57604c19831215610a52575f809550955050505050610b1f565b825f03600a0a9150818481610a6957610a69611f3e565b0495505084029091149150610b1f9050565b5f831315610b1457604d831315610ab85760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610289565b82600a0a9150815f1981610ace57610ace611f3e565b04841115610b025760405163c849483b60e01b8152600481018a90526024810189905260ff88166044820152606401610289565b5091909102925060019150610b1f9050565b509193506001925050505b935093915050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00546002036109bc57604051633ee5aeb560e01b815260040160405180910390fd5b6105148383836001610df1565b5f805f805f610b858787610e3b565b9250925092505f80610b978585610e97565b9150915081838015610ba65750815b9650965050505050509250929050565b80471015610be05760405163cf47918160e01b815247600482015260248101829052604401610289565b610bf9828260405180602001604052805f815250610f84565b15610c02575050565b3d15610c1457610c10610f99565b5050565b60405163d6bda27560e01b815260040160405180910390fd5b335f8181523060209081526040808320815160a0810183528083018581526060808301879052608083018190529082528185015282518581529384018581528484019093529093909291905b86518110156108c557868181518110610c9457610c94611a0c565b602002602001015193505f845f015160400151511115610de9575f845f01515f01516001600160a01b031663d04dfe236040518060e00160405280885f0151602001516001600160a01b03168152602001898152602001885f01516040015181526020015f8152602001610d0c8d8a60200151610fa4565b8152602001878152602001868152506040518263ffffffff1660e01b8152600401610d379190611fd9565b5f60405180830381865afa158015610d51573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d7891908101906120da565b9150505f81511115610de75784516020015160405163012c676d60e21b81526001600160a01b03909116906304b19db490610db9908a908590600401612190565b5f604051808303815f87803b158015610dd0575f80fd5b505af1158015610de2573d5f803e3d5ffd5b505050505b505b600101610c79565b60405163a9059cbb60e01b5f8181526001600160a01b038616600452602485905291602083604481808b5af1925060015f51148316610925578383151615610919573d5f823e3d81fd5b5f808060ff841681037f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff861115610e8657600a860460018201600a88065f1493509350935050610e90565b8593509150600190505b9250925092565b5f601b83900b8314838382610efb577d90e40fbeea1d3a4abc8955e946fe31cdcf66f634e1000000000000000000860515610edb57620186a0860595506005850194505b8586601b0b14610ef657600a86059550846001019450610edb565b610f11565b855f03610f1157505f9250600191506105fb9050565b848560030b14610f54575f851215610f3157505f92508291506105fb9050565b60405163d556b11160e01b81526004810183905260248101829052604401610289565b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841660e084901b1791509250929050565b5f805f83516020850186885af1949350505050565b6040513d5f823e3d81fd5b60605f825167ffffffffffffffff811115610fc157610fc16115b3565b604051908082528060200260200182016040528015610fea578160200160208202803683370190505b5090505f80845111610ffc575f611002565b83516001015b85516001010190505f8167ffffffffffffffff811115611024576110246115b3565b60405190808252806020026020018201604052801561105757816020015b60608152602001906001900390816110425790505b5090505f61107b604080516002815233602082015230818301526060810190915290565b82828151811061108d5761108d611a0c565b60200260200101819052505f5b87518110156110ea5781806001019250508781815181106110bd576110bd611a0c565b60200260200101518383815181106110d7576110d7611a0c565b602090810291909101015260010161109a565b5085511561127c5780806001019150508382828151811061110d5761110d611a0c565b60200260200101819052505f5b865181101561127a576111c987828151811061113857611138611a0c565b60200260200101515f01516111a66111748a858151811061115b5761115b611a0c565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b8984815181106111b8576111b8611a0c565b602002602001015160400151611286565b6111e957604051630a57f30960e31b815260048101829052602401610289565b8681815181106111fb576111fb611a0c565b60200260200101515f01516001600160a01b03165f1b85828151811061122357611223611a0c565b602002602001018181525050818060010192505086818151811061124957611249611a0c565b60200260200101516020015183838151811061126757611267611a0c565b602090810291909101015260010161111a565b505b5095945050505050565b5f836001600160a01b03163b5f036112e4575f806112a485856112f9565b5090925090505f8160038111156112bd576112bd6121a8565b1480156112db5750856001600160a01b0316826001600160a01b0316145b925050506112f2565b6112ef84848461133f565b90505b9392505050565b5f805f8351604103611330576020840151604085015160608601515f1a61132288828585611390565b955095509550505050610e90565b505081515f9150600290610e90565b805160408051630b135d3f60e11b8082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156113c957505f9150600390508261144e565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561141a573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661144557505f92506001915082905061144e565b92505f91508190505b9450945094915050565b5f60208284031215611468575f80fd5b81356001600160e01b0319811681146112f2575f80fd5b6001600160a01b0381168114610214575f80fd5b5f805f805f8060a087890312156114a8575f80fd5b86356114b38161147f565b955060208701356114c38161147f565b94506040870135935060608701359250608087013567ffffffffffffffff808211156114ed575f80fd5b818901915089601f830112611500575f80fd5b81358181111561150e575f80fd5b8a602082850101111561151f575f80fd5b6020830194508093505050509295509295509295565b5f805f60608486031215611547575f80fd5b83356115528161147f565b9250602084013567ffffffffffffffff8082111561156e575f80fd5b9085019060c08288031215611581575f80fd5b90925060408501359080821115611596575f80fd5b508401604081870312156115a8575f80fd5b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156115ea576115ea6115b3565b60405290565b6040805190810167ffffffffffffffff811182821017156115ea576115ea6115b3565b604051601f8201601f1916810167ffffffffffffffff8111828210171561163c5761163c6115b3565b604052919050565b5f82601f830112611653575f80fd5b813567ffffffffffffffff81111561166d5761166d6115b3565b611680601f8201601f1916602001611613565b818152846020838601011115611694575f80fd5b816020850160208301375f918101602001919091529392505050565b5f602082840312156116c0575f80fd5b813567ffffffffffffffff8111156116d6575f80fd5b6116e284828501611644565b949350505050565b5f6001820161170757634e487b7160e01b5f52601160045260245ffd5b5060010190565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f6001600160a01b038089168352876020840152808716604084015285606084015280851660808401525060c060a083015261177b60c083018461170e565b98975050505050505050565b5f60208284031215611797575f80fd5b5051919050565b5f67ffffffffffffffff8211156117b7576117b76115b3565b5060051b60200190565b5f82601f8301126117d0575f80fd5b813560206117e56117e08361179e565b611613565b82815260059290921b84018101918181019086841115611803575f80fd5b8286015b848110156118ff57803567ffffffffffffffff80821115611826575f80fd5b908801906060828b03601f1901121561183d575f80fd5b6118456115c7565b868301356118528161147f565b815260408381013583811115611866575f80fd5b8401603f81018d13611876575f80fd5b888101356118866117e08261179e565b81815260059190911b82018301908a8101908f8311156118a4575f80fd5b928401925b828410156118c25783358252928b0192908b01906118a9565b858c01525050506060840135838111156118da575f80fd5b6118e88d8a83880101611644565b918301919091525085525050918301918301611807565b509695505050505050565b5f6040823603121561191a575f80fd5b6119226115f0565b823567ffffffffffffffff80821115611939575f80fd5b81850191506060823603121561194d575f80fd5b6119556115c7565b82356119608161147f565b815260208301356119708161147f565b6020820152604083013582811115611986575f80fd5b61199236828601611644565b604083015250835260208501359150808211156119ad575f80fd5b506119ba368286016117c1565b60208301525092915050565b5f808335601e198436030181126119db575f80fd5b83018035915067ffffffffffffffff8211156119f5575f80fd5b6020019150600581901b36038213156105fb575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112611a34575f80fd5b9190910192915050565b5f8235609e19833603018112611a34575f80fd5b5f808335601e19843603018112611a67575f80fd5b83018035915067ffffffffffffffff821115611a81575f80fd5b6020019150600681901b36038213156105fb575f80fd5b5f60208284031215611aa8575f80fd5b81356112f28161147f565b5f808335601e19843603018112611ac8575f80fd5b830160208101925035905067ffffffffffffffff811115611ae7575f80fd5b8060051b36038213156105fb575f80fd5b5f8235605e19833603018112611b0c575f80fd5b90910192915050565b5f808335601e19843603018112611b2a575f80fd5b830160208101925035905067ffffffffffffffff811115611b49575f80fd5b8036038213156105fb575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f808335601e19843603018112611b94575f80fd5b830160208101925035905067ffffffffffffffff811115611bb3575f80fd5b8060061b36038213156105fb575f80fd5b8183525f60208085019450825f5b85811015611c0a578135611be58161147f565b6001600160a01b03168752818301358388015260409687019690910190600101611bd2565b509495945050505050565b8183526020808401935f91600585811b8301820185855b88811015611cee57858303601f19018a52611c478289611af8565b60608135611c548161147f565b6001600160a01b03168552611c6b82880183611ab3565b82898801528083880152608092507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115611ca5575f80fd5b871b808288850137860190506040611cbf84820185611b15565b9450838884030182890152611cd78484018683611b57565b9e8a019e9750505093870193505050600101611c2c565b509098975050505050505050565b5f602080835260e08301843582850152604082860135818601526060818701358187015280870135801515808214611d32575f80fd5b8060808901525050611d476080880188611ab3565b60c060a08901529384905261010093848801600582901b89018601835f5b84811015611ec3578b830360ff19018452813536879003607e19018112611d8a575f80fd5b8601803536829003609e19018112611da0575f80fd5b6080855281018035611db18161147f565b6001600160a01b038082166080880152611dcd8e840184611af8565b915060a0808801528135611de08161147f565b8116610120880152818e0135611df58161147f565b16610140870152611e08818c0182611b15565b91508a610160880152611e2061018088018383611b57565b915050611e2f8b830183611b7f565b607f19808985030160c08a0152611e47848385611bc4565b9350611e558d860186611b7f565b93509150808985030160e08a015250611e6f838383611bc4565b9250505060808201358c8701528c8301358d8701528a8301358b870152611e988a840184611ab3565b935091508581038a870152611eae818484611c15565b968d019695505050918a019150600101611d65565b5050611ed260a08c018c611b15565b8b8303601f190160c08d015298509650611eed818989611b57565b9b9a5050505050505050505050565b5f8060408385031215611f0d575f80fd5b505080516020909101519092909150565b5f60208284031215611f2e575f80fd5b815160ff811681146112f2575f80fd5b634e487b7160e01b5f52601260045260245ffd5b5f815180845260208085019450602084015f5b83811015611c0a57815187529582019590820190600101611f65565b5f8282518085526020808601955060208260051b840101602086015f5b84811015611fcc57601f19868403018952611fba838351611f52565b98840198925090830190600101611f9e565b5090979650505050505050565b602081526001600160a01b038251166020820152602082015160408201525f604083015160e0606084015261201261010084018261170e565b9050606084015160808401526080840151601f19808584030160a086015261203a8383611f81565b925060a08601519150808584030160c08601526120578383611f52565b925060c08601519150808584030160e0860152506120758282611f52565b95945050505050565b5f82601f83011261208d575f80fd5b8151602061209d6117e08361179e565b8083825260208201915060208460051b8701019350868411156120be575f80fd5b602086015b848110156118ff57805183529183019183016120c3565b5f80604083850312156120eb575f80fd5b825167ffffffffffffffff80821115612102575f80fd5b818501915085601f830112612115575f80fd5b815160206121256117e08361179e565b82815260059290921b84018101918181019089841115612143575f80fd5b948201945b8386101561216157855182529482019490820190612148565b91880151919650909350505080821115612179575f80fd5b506121868582860161207e565b9150509250929050565b828152604060208201525f6116e26040830184611f52565b634e487b7160e01b5f52602160045260245ffd"; diff --git a/src/lib/deploy/LibRaindexDeploy.sol b/src/lib/deploy/LibRaindexDeploy.sol index 9371608cb0..aa3849f1fe 100644 --- a/src/lib/deploy/LibRaindexDeploy.sol +++ b/src/lib/deploy/LibRaindexDeploy.sol @@ -123,6 +123,15 @@ library LibRaindexDeploy { bytes32 constant RAINDEX_DEPLOYED_CODEHASH_0_1_9 = 0x774ca4c194abf0720bca6c033580762029a80291feefd0a4b7855b16bcbbf7a9; + /// The deployed address of the `RaindexV6` contract at the published `0.1.10` + /// tag. (Changed in 0.1.10 — per-(user,token) dust-credit ledger.) + address constant RAINDEX_DEPLOYED_ADDRESS_0_1_10 = 0x66F51a9C29480491C9282D99cf324e9f419A4e1d; + + /// The runtime code hash of the `RaindexV6` contract at the published `0.1.10` + /// tag. + bytes32 constant RAINDEX_DEPLOYED_CODEHASH_0_1_10 = + 0x670aa891cb8fcb7166ecf8031238f6287ead1ac018d6353af04dfd720b146e75; + /// The address of the `RaindexV6SubParser` contract when deployed with /// the rain standard zoltu deployer. address constant SUB_PARSER_DEPLOYED_ADDRESS = SUB_PARSER_ADDR; @@ -212,6 +221,15 @@ library LibRaindexDeploy { bytes32 constant SUB_PARSER_DEPLOYED_CODEHASH_0_1_9 = 0x704aadc1ed56f63ff918ab219e6681a5d2851d774e2ee136bbe7904ea3b2fdcd; + /// The deployed address of the `RaindexV6SubParser` contract at the + /// published `0.1.10` tag. (Unchanged from `0.1.2`.) + address constant SUB_PARSER_DEPLOYED_ADDRESS_0_1_10 = 0x09Bc7AF266012F44fb41D8Bd682da931666605e1; + + /// The runtime code hash of the `RaindexV6SubParser` contract at the + /// published `0.1.10` tag. + bytes32 constant SUB_PARSER_DEPLOYED_CODEHASH_0_1_10 = + 0x704aadc1ed56f63ff918ab219e6681a5d2851d774e2ee136bbe7904ea3b2fdcd; + /// The address of the `RouteProcessor4` contract when deployed with the /// rain standard zoltu deployer. address constant ROUTE_PROCESSOR_DEPLOYED_ADDRESS = ROUTE_PROCESSOR_ADDR; @@ -301,6 +319,15 @@ library LibRaindexDeploy { bytes32 constant ROUTE_PROCESSOR_DEPLOYED_CODEHASH_0_1_9 = 0xeb3745a79c6ba48e8767b9c355b8e7b79f9d6edeca004e4bb91be4de515a7eeb; + /// The deployed address of the `RouteProcessor4` contract at the published + /// `0.1.10` tag. (Unchanged from `0.1.0`.) + address constant ROUTE_PROCESSOR_DEPLOYED_ADDRESS_0_1_10 = 0x6E2d0e71d900474b262E545Bc4C98b71ab368d21; + + /// The runtime code hash of the `RouteProcessor4` contract at the published + /// `0.1.10` tag. + bytes32 constant ROUTE_PROCESSOR_DEPLOYED_CODEHASH_0_1_10 = + 0xeb3745a79c6ba48e8767b9c355b8e7b79f9d6edeca004e4bb91be4de515a7eeb; + /// The address of the `GenericPoolRaindexV6ArbOrderTaker` contract when /// deployed with the rain standard zoltu deployer. address constant GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS = GENERIC_POOL_ARB_OT_ADDR; @@ -393,6 +420,16 @@ library LibRaindexDeploy { bytes32 constant GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH_0_1_9 = 0xc4492cb22d918a3f0d41f13e533744ef03a2e7f744ec0a43b79d97a04c537544; + /// The deployed address of the `GenericPoolRaindexV6ArbOrderTaker` contract + /// at the published `0.1.10` tag. (Changed in 0.1.10 — embeds the new raindex + /// address.) + address constant GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS_0_1_10 = 0xe2a825c9C2b52F7c73f30080680DdB90f36ed9c3; + + /// The runtime code hash of the `GenericPoolRaindexV6ArbOrderTaker` contract + /// at the published `0.1.10` tag. + bytes32 constant GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH_0_1_10 = + 0xd3453fd739378f1ccce8181a1ba3554db33e3fc13f6eeda83d2abc716c45d89b; + /// The address of the `RouteProcessorRaindexV6ArbOrderTaker` contract /// when deployed with the rain standard zoltu deployer. address constant ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS = RP_ARB_OT_ADDR; @@ -494,6 +531,17 @@ library LibRaindexDeploy { bytes32 constant ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH_0_1_9 = 0xc3fb3bb0355fee22e54cade57f5ff828478d59f34fdd8057bc0bc6a11b3d48fc; + /// The deployed address of the `RouteProcessorRaindexV6ArbOrderTaker` + /// contract at the published `0.1.10` tag. (Changed in 0.1.10 — embeds the + /// new raindex address.) + address constant ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS_0_1_10 = + 0xDd436bd0e92389e1c45E6Af5F0C2D989c626d49e; + + /// The runtime code hash of the `RouteProcessorRaindexV6ArbOrderTaker` + /// contract at the published `0.1.10` tag. + bytes32 constant ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH_0_1_10 = + 0xebca76aecd91efeee0840b70028dda00c90b06266c1bea04d5367a58d5e7f751; + /// The address of the `GenericPoolRaindexV6FlashBorrower` contract when /// deployed with the rain standard zoltu deployer. address constant GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS = GENERIC_POOL_FB_ADDR; @@ -586,6 +634,16 @@ library LibRaindexDeploy { bytes32 constant GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH_0_1_9 = 0xed618063fd6ffc7558e4588ea6357356e781d660fa22caa292a2f9aeaa21996f; + /// The deployed address of the `GenericPoolRaindexV6FlashBorrower` contract + /// at the published `0.1.10` tag. (Changed in 0.1.10 — embeds the new raindex + /// address.) + address constant GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS_0_1_10 = 0x94e275d0eAf27c28C4737b91f8CD9D1DD9132019; + + /// The runtime code hash of the `GenericPoolRaindexV6FlashBorrower` contract + /// at the published `0.1.10` tag. + bytes32 constant GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH_0_1_10 = + 0x3438f85dace78d284e0eb33f8a245750498a37dfde867325a0760cf022e8fdb7; + uint256 constant RAINDEX_START_BLOCK_ARBITRUM = 473030678; uint256 constant RAINDEX_START_BLOCK_BASE = 47278140; uint256 constant RAINDEX_START_BLOCK_FLARE = 62835540; diff --git a/test/concrete/raindex/PrecisionAttackMutableDecimalsToken.sol b/test/concrete/raindex/PrecisionAttackMutableDecimalsToken.sol new file mode 100644 index 0000000000..fe81c34761 --- /dev/null +++ b/test/concrete/raindex/PrecisionAttackMutableDecimalsToken.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {ERC20} from "@openzeppelin-contracts-5.6.1/token/ERC20/ERC20.sol"; + +contract PrecisionAttackMutableDecimalsToken is ERC20 { + uint8 public dec; + + constructor(uint8 d) ERC20("Mut", "MUT") { + dec = d; + } + + function setDecimals(uint8 d) external { + dec = d; + } + + function decimals() public view override returns (uint8) { + return dec; + } + + function mint(address to, uint256 amount) external { + _mint(to, amount); + } +} diff --git a/test/concrete/raindex/RaindexV6.deposit.entask.t.sol b/test/concrete/raindex/RaindexV6.deposit.entask.t.sol index b398fb3457..004512d864 100644 --- a/test/concrete/raindex/RaindexV6.deposit.entask.t.sol +++ b/test/concrete/raindex/RaindexV6.deposit.entask.t.sol @@ -26,12 +26,15 @@ contract RaindexV6DepositEnactTest is RaindexV6ExternalRealTest { // ReentrancyGuard.REENTRANCY_GUARD_STORAGE bytes32 reentrancyGuardStorage = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; - assertEq(reads.length, 5); + // pullTokens reads sDustCredit (2 SLOADs of the Float slot) and writes it + // back (1 SSTORE), adding 2 reads and 1 write over the pre-dust-credit + // 5 reads (reentrancy x3 + vault balance x2) / 3 writes. + assertEq(reads.length, 7); assertEq(reads[0], reentrancyGuardStorage); assertEq(reads[1], reentrancyGuardStorage); assertEq(reads[reads.length - 1], reentrancyGuardStorage); - assertEq(writes.length, 3); + assertEq(writes.length, 4); assertEq(writes[0], reentrancyGuardStorage); assertEq(writes[writes.length - 1], reentrancyGuardStorage); } diff --git a/test/concrete/raindex/RaindexV6.deposit.t.sol b/test/concrete/raindex/RaindexV6.deposit.t.sol index 2d450ec2a6..e7705a5ac9 100644 --- a/test/concrete/raindex/RaindexV6.deposit.t.sol +++ b/test/concrete/raindex/RaindexV6.deposit.t.sol @@ -199,11 +199,12 @@ contract RaindexV6DepositTest is RaindexV6ExternalMockTest { assertEq(vm.getRecordedLogs().length, 1, "logs"); // - reentrancy guard x3 // - vault balance floats x2 - // - token decimals x2 - assertTrue(reads.length == 5, "reads"); - // // - reentrancy guard x2 - // // - vault balance x1 - assertTrue(writes.length == 4 || writes.length == 3, "writes"); + // - dust credit floats x2 (sDustCredit SLOAD in pullTokens) + assertTrue(reads.length == 7, "reads"); + // - reentrancy guard x2 + // - vault balance x1 + // - dust credit x1 (sDustCredit SSTORE in pullTokens) + assertTrue(writes.length == 4, "writes"); assertTrue( iRaindex.vaultBalance2(actions[i].depositor, actions[i].token, actions[i].vaultId) .eq(actions[i].amount.add(vaultBalanceBefore)), diff --git a/test/concrete/raindex/RaindexV6.dustCredit.conservationAttack.t.sol b/test/concrete/raindex/RaindexV6.dustCredit.conservationAttack.t.sol new file mode 100644 index 0000000000..8c7a994fa5 --- /dev/null +++ b/test/concrete/raindex/RaindexV6.dustCredit.conservationAttack.t.sol @@ -0,0 +1,302 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Test} from "forge-std-1.16.1/src/Test.sol"; +import {Float, LibDecimalFloat} from "rain-math-float-0.1.1/src/lib/LibDecimalFloat.sol"; +import {MockToken} from "test/util/concrete/MockToken.sol"; +import {LibRainDeploy} from "rain-deploy-0.1.2/src/lib/LibRainDeploy.sol"; +import {LibTOFUTokenDecimals} from "rain-tofu-erc20-decimals-0.1.1/src/lib/LibTOFUTokenDecimals.sol"; +import { + RaindexV6DustCreditConservationAttackHarness +} from "test/concrete/raindex/RaindexV6DustCreditConservationAttackHarness.sol"; + +/// @title Adversarial conservation attack on the dust-credit ledger. +contract RaindexV6DustCreditConservationAttackTest is Test { + using LibDecimalFloat for Float; + + RaindexV6DustCreditConservationAttackHarness internal harness; + address internal owner = makeAddr("owner"); + + function setUp() external { + LibRainDeploy.etchZoltuFactory(vm); + LibRainDeploy.deployZoltu(LibTOFUTokenDecimals.TOFU_DECIMALS_EXPECTED_CREATION_CODE); + harness = RaindexV6DustCreditConservationAttackHarness( + payable(address(uint160(uint256(keccak256("dust.credit.conservation.attack.harness"))))) + ); + vm.etch(address(harness), type(RaindexV6DustCreditConservationAttackHarness).runtimeCode); + } + + function _mkToken(uint8 decimals) internal returns (MockToken token) { + token = new MockToken("Token", "TKN", decimals); + // Stay well under int256 max so the int256 casts in the conservation + // checks never overflow on the harness side (this is a test-harness + // limit, not a contract limit). + uint256 supply = uint256(type(int256).max) / 4; + token.mint(owner, supply); + token.mint(address(harness), supply); + vm.prank(owner); + token.approve(address(harness), type(uint256).max); + } + + // Helper: assert 0 <= credit < 1 base unit (1 base unit = 10^-decimals token units). + function _assertCreditInvariant(MockToken token, uint8 decimals) internal view { + Float credit = harness.exposedDustCredit(owner, address(token)); + assertTrue(!credit.lt(LibDecimalFloat.FLOAT_ZERO), "credit negative"); + Float oneBaseUnit = LibDecimalFloat.packLossless(1, -int256(uint256(decimals))); + assertTrue(credit.lt(oneBaseUnit), "credit >= 1 base unit"); + } + + /// ATTACK 1: very large amount on a low-decimals token, near uint256 transfer + /// limits, to probe the int224 truncation in the from-fixed round trip. + /// We use an amount with significant low-order digits so any truncation in + /// packLossy would show up as a wrong credit / wrong conservation. + function testLargeAmountRoundTripPull() external { + uint8 decimals = 6; + MockToken token = _mkToken(decimals); + + // amount = 1.2345...e40 token units with a fractional sub-base-unit tail. + // coefficient 123456789012345678901234567890123456789 (39 sig digits), + // exponent -7 => value has a 0.x base-unit fractional remainder. + Float amount = LibDecimalFloat.packLossless(123456789012345678901234567890123456789, -7); + + uint256 balBefore = token.balanceOf(address(harness)); + (uint256 moved,) = harness.exposedPull(owner, address(token), amount); + uint256 balAfter = token.balanceOf(address(harness)); + assertEq(balAfter - balBefore, moved, "moved matches real transfer"); + + _assertCreditInvariant(token, decimals); + + // Conservation: realDelta(token units) == amount + credit (no prior credit). + Float realDelta = LibDecimalFloat.fromFixedDecimalLosslessPacked(moved, decimals); + Float credit = harness.exposedDustCredit(owner, address(token)); + // realDelta should equal amount + credit (pull over-pulls so realDelta>=amount). + assertTrue(realDelta.eq(amount.add(credit)), "conservation pull large"); + } + + /// ATTACK 2: alternate pull/push at sub-base-unit boundaries across many + /// steps, tracking conservation exactly, on an 18-decimal token. + function testAlternatingBoundary() external { + uint8 decimals = 18; + MockToken token = _mkToken(decimals); + + int256 netRequestedTenths = 0; + int256 startBal = int256(token.balanceOf(address(harness))); + + // Sequence of (isPull, tenthsOfBaseUnit). + int256[10] memory amounts = [int256(15), 7, 23, 4, 99, 1, 250, 13, 6, 88]; + bool[10] memory pulls = [true, false, true, true, false, false, true, false, true, false]; + + for (uint256 i = 0; i < 10; i++) { + Float amount = LibDecimalFloat.packLossless(amounts[i], -int256(uint256(decimals)) - 1); + if (pulls[i]) { + harness.exposedPull(owner, address(token), amount); + netRequestedTenths += amounts[i]; + } else { + harness.exposedPush(owner, address(token), amount); + netRequestedTenths -= amounts[i]; + } + int256 delta = int256(token.balanceOf(address(harness))) - startBal; + Float realDelta = LibDecimalFloat.packLossless(delta, -int256(uint256(decimals))); + Float netReq = LibDecimalFloat.packLossless(netRequestedTenths, -int256(uint256(decimals)) - 1); + Float credit = harness.exposedDustCredit(owner, address(token)); + assertTrue(realDelta.eq(netReq.add(credit)), "conservation alt"); + _assertCreditInvariant(token, decimals); + } + } + + /// ATTACK 3: high-decimals token (36) with a large amount. Probes whether the + /// credit (very small, ~1e-36) can be silently dropped by the float sub when + /// subtracting from a large amount (exponent gap), and whether toFixed reverts. + function testHighDecimalsCreditNotDropped() external { + uint8 decimals = 36; + MockToken token = _mkToken(decimals); + + // Seed a credit with a sub-base-unit pull: 0.5 base units = 5e-37. + Float seed = LibDecimalFloat.packLossless(5, -37); + harness.exposedPull(owner, address(token), seed); + Float credit0 = harness.exposedDustCredit(owner, address(token)); + // 0.5 base unit pull rounds up to 1 base unit, credit = 1e-36 - 5e-37 = 5e-37. + assertTrue(credit0.eq(LibDecimalFloat.packLossless(5, -37)), "seed credit"); + + // Now a large pull: 1e30 token units (huge). Exponent gap to credit ~ 66. + Float big = LibDecimalFloat.packLossless(1, 30); + uint256 balBefore = token.balanceOf(address(harness)); + (uint256 moved,) = harness.exposedPull(owner, address(token), big); + uint256 realMoved = token.balanceOf(address(harness)) - balBefore; + assertEq(realMoved, moved, "moved matches transfer"); + + _assertCreditInvariant(token, decimals); + + // Conservation: realDelta(token units) == effective_requested + creditNew. + // Total requested across both moves = seed + big. + Float totalRequested = seed.add(big); + // realDelta total = first move (1 base unit = 1e-36) + this move. + Float realDeltaTotal = LibDecimalFloat.fromFixedDecimalLosslessPacked(1, decimals) + .add(LibDecimalFloat.fromFixedDecimalLosslessPacked(realMoved, decimals)); + Float creditNew = harness.exposedDustCredit(owner, address(token)); + assertTrue(realDeltaTotal.eq(totalRequested.add(creditNew)), "conservation high-decimals"); + } + + /// ATTACK 4: push where amount + credit must realize, with an amount large + /// enough relative to the credit that the float add might drop the credit. + function testHighDecimalsPushCreditNotDropped() external { + uint8 decimals = 36; + MockToken token = _mkToken(decimals); + + // Seed credit via a sub-base-unit push: 0.5 base units -> pushes 0, credit 0.5. + Float seed = LibDecimalFloat.packLossless(5, -37); + harness.exposedPush(owner, address(token), seed); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(5, -37)), + "push seed credit" + ); + + // Large push. + Float big = LibDecimalFloat.packLossless(1, 30); + uint256 balBefore = token.balanceOf(address(harness)); + (uint256 moved,) = harness.exposedPush(owner, address(token), big); + uint256 realMoved = balBefore - token.balanceOf(address(harness)); + assertEq(realMoved, moved, "push moved matches"); + _assertCreditInvariant(token, decimals); + } + + /// ATTACK 5: extreme decimals (60). One base unit = 1e-60. Does the machinery + /// hold and not revert / not break the invariant? + function testExtremeDecimals() external { + uint8 decimals = 60; + MockToken token = _mkToken(decimals); + + Float amount = LibDecimalFloat.packLossless(15, -61); // 1.5 base units + (uint256 moved,) = harness.exposedPull(owner, address(token), amount); + assertEq(moved, 2, "1.5 rounds up to 2 at 60 decimals"); + _assertCreditInvariant(token, decimals); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(5, -61)), "credit 0.5" + ); + } + + /// ATTACK 7: deliberately force the exponent-gap drop in `effective = + /// amount.sub(credit)`. After maximization both coefficients are ~67 digits; + /// when their exponents differ by > 76 the smaller operand (the credit) is + /// dropped entirely by LibDecimalFloatImplementation.add. With decimals=18, + /// a seeded ~1e-18 credit (normalized exp ~ -85) versus an amount ~1e70 token + /// units (normalized exp ~ +3) has a gap > 76. If the credit is dropped the + /// PRIOR credit is silently stranded (re-introducing the original L01 dust + /// loss) even though per-move 0<=credit<1 still holds. This probes the + /// cross-move "every credit is realized" property, the PR's central claim. + function testExponentGapDropsCredit() external { + uint8 decimals = 18; + MockToken token = _mkToken(decimals); // supply ~1.4e76 base units + + // Seed a credit: pull 0.5 base units -> rounds up to 1, credit 0.5 base + // units = 5e-19 token units. + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(5, -19)); + Float seededCredit = harness.exposedDustCredit(owner, address(token)); + assertTrue(seededCredit.eq(LibDecimalFloat.packLossless(5, -19)), "seeded 0.5 credit"); + + // A huge amount in token units. supply/4 ~ 1.4e76 base units = 1.4e58 + // token units. Use coefficient*10^exp with enough magnitude that the + // normalized exponent gap to the ~5e-19 credit exceeds 76, but the base + // unit count stays within the minted supply and toFixed does not overflow. + // 1.4e58 token units -> exponent gap ~ 58+19 = 77 (> 76). Use 1e58. + Float big = LibDecimalFloat.packLossless(1, 58); + + uint256 balBefore = token.balanceOf(address(harness)); + (uint256 moved,) = harness.exposedPull(owner, address(token), big); + uint256 realMoved = token.balanceOf(address(harness)) - balBefore; + assertEq(realMoved, moved, "moved matches transfer"); + + Float creditAfter = harness.exposedDustCredit(owner, address(token)); + // Hard invariants must still hold regardless of any drop. + _assertCreditInvariant(token, decimals); + + // Now drive the credit toward realization with a sub-unit pull and see if + // the previously-seeded 0.5 was preserved. If the big pull dropped it, the + // ledger lost track of real tokens the orderbook holds. + emit log_named_bytes32("seededCredit", Float.unwrap(seededCredit)); + emit log_named_bytes32("creditAfterBig", Float.unwrap(creditAfter)); + emit log_named_uint("movedBig", moved); + + // Characterize the stranding: the big pull moved exactly the requested + // base units (1e76) with NO over-pull, and the previously-seeded 0.5 + // credit was silently dropped to zero rather than realized. + assertEq(moved, 1e76, "big pull moved exactly the requested base units"); + assertTrue(creditAfter.isZero(), "STRANDING: seeded 0.5 credit silently dropped to zero by exponent gap"); + + // The 0.5 base unit (5e-19 token units) that was stranded is BELOW the + // Float resolution next to a 1e58-token-unit amount (77 OOM apart), so at + // Float precision the stated conservation invariant still appears to hold: + // realDeltaTotal and (totalRequested + creditAfter) are the SAME Float. + // The physical stranding is real (the contract's raw ERC20 balance carries + // the extra 0.5 base unit with no ledger entry) but invisible/irrecoverable + // at this magnitude. This is the pre-PR L01 dust, re-stranded at extreme + // amounts; it does NOT violate 0<=credit<1 or the Float-precision + // conservation equation. + (Float realBigDelta,) = LibDecimalFloat.fromFixedDecimalLossyPacked(realMoved, decimals); + Float realDeltaTotal = LibDecimalFloat.fromFixedDecimalLosslessPacked(1, decimals).add(realBigDelta); + Float totalRequested = LibDecimalFloat.packLossless(5, -19).add(big); + Float conserved = totalRequested.add(creditAfter); + // At Float precision they ARE equal: the stated invariant survives even as + // the credit is physically stranded. + assertTrue( + realDeltaTotal.eq(conserved), "Float-precision conservation still holds; stranding is sub-resolution" + ); + } + + /// ATTACK 8: broaden the PR fuzz beyond its 6-decimal / 25.5-base-unit cap. + /// Random decimals in [0,30] and amounts spanning sub-unit to ~6.5e9 base + /// units, asserting hard invariants after every move. Catches any rounding / + /// sign bug the narrow PR fuzz misses. + /// forge-config: default.fuzz.runs = 1500 + function testWideFuzz(uint8 decimalsRaw, bool[] memory isPull, uint64[] memory amts) external { + uint8 decimals = uint8(bound(decimalsRaw, 0, 30)); + MockToken token = _mkToken(decimals); + + vm.assume(isPull.length > 0 && amts.length > 0); + uint256 n = isPull.length < amts.length ? isPull.length : amts.length; + vm.assume(n > 0); + if (n > 40) n = 40; + + Float oneBaseUnit = LibDecimalFloat.packLossless(1, -int256(uint256(decimals))); + + for (uint256 i = 0; i < n; i++) { + // amount in token units: amts[i] base units, expressed as a Float at + // exponent -decimals, but offset the exponent by -1 half the time to + // exercise genuine sub-base-unit fractions. + int256 exp = -int256(uint256(decimals)) - int256(i % 2); + Float amount = LibDecimalFloat.packLossless(int256(uint256(amts[i])), exp); + if (isPull[i]) { + harness.exposedPull(owner, address(token), amount); + } else { + harness.exposedPush(owner, address(token), amount); + } + Float credit = harness.exposedDustCredit(owner, address(token)); + assertTrue(!credit.lt(LibDecimalFloat.FLOAT_ZERO), "fuzz: credit negative"); + assertTrue(credit.lt(oneBaseUnit), "fuzz: credit >= 1 base unit"); + } + } + + /// ATTACK 6: stress the int224 boundary directly. Pull an amount whose base + /// unit count exceeds int224 max (~6.7e66) WITH significant low digits, on a + /// 0-decimals token (so amount==base units and there are no trailing zeros to + /// rescue the round trip). If packLossy truncation corrupts the round trip the + /// derived credit goes wrong / negative. + function testInt224BoundaryZeroDecimals() external { + uint8 decimals = 0; + MockToken token = _mkToken(decimals); + + // A 60-significant-digit integer amount of base units, no trailing zeros. + // 123...789 repeated. int224 max ~ 1.35e67 so 60 digits (~1e59) is safe; + // push to ~67 digits to flirt with the boundary but stay representable. + Float amount = LibDecimalFloat.packLossless(123456789012345678901234567890123456789012345678901234567891, 0); + uint256 balBefore = token.balanceOf(address(harness)); + (uint256 moved,) = harness.exposedPull(owner, address(token), amount); + assertEq(token.balanceOf(address(harness)) - balBefore, moved, "moved matches"); + _assertCreditInvariant(token, decimals); + // 0 decimals => integer amount is lossless, credit must be exactly zero. + assertTrue(harness.exposedDustCredit(owner, address(token)).isZero(), "0-dec lossless => no credit"); + Float realDelta = LibDecimalFloat.fromFixedDecimalLosslessPacked(moved, decimals); + assertTrue(realDelta.eq(amount), "0-dec conservation exact"); + } +} diff --git a/test/concrete/raindex/RaindexV6.dustCredit.precisionAttack.t.sol b/test/concrete/raindex/RaindexV6.dustCredit.precisionAttack.t.sol new file mode 100644 index 0000000000..6288294b17 --- /dev/null +++ b/test/concrete/raindex/RaindexV6.dustCredit.precisionAttack.t.sol @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Test} from "forge-std-1.16.1/src/Test.sol"; +import {Float, LibDecimalFloat} from "rain-math-float-0.1.1/src/lib/LibDecimalFloat.sol"; +import {MockToken} from "test/util/concrete/MockToken.sol"; +import {LibRainDeploy} from "rain-deploy-0.1.2/src/lib/LibRainDeploy.sol"; +import {LibTOFUTokenDecimals} from "rain-tofu-erc20-decimals-0.1.1/src/lib/LibTOFUTokenDecimals.sol"; +import {ITOFUTokenDecimals, TOFUOutcome} from "rain-tofu-erc20-decimals-0.1.1/src/interface/ITOFUTokenDecimals.sol"; +import { + RaindexV6DustCreditPrecisionAttackHarness +} from "test/concrete/raindex/RaindexV6DustCreditPrecisionAttackHarness.sol"; +import {PrecisionAttackMutableDecimalsToken} from "test/concrete/raindex/PrecisionAttackMutableDecimalsToken.sol"; + +contract RaindexV6DustCreditPrecisionAttackTest is Test { + using LibDecimalFloat for Float; + + RaindexV6DustCreditPrecisionAttackHarness internal harness; + address internal owner = makeAddr("owner"); + + function setUp() external { + LibRainDeploy.etchZoltuFactory(vm); + LibRainDeploy.deployZoltu(LibTOFUTokenDecimals.TOFU_DECIMALS_EXPECTED_CREATION_CODE); + harness = RaindexV6DustCreditPrecisionAttackHarness( + payable(address(uint160(uint256(keccak256("dust.credit.precision.attack"))))) + ); + vm.etch(address(harness), type(RaindexV6DustCreditPrecisionAttackHarness).runtimeCode); + } + + function _newToken(uint8 dec) internal returns (MockToken token) { + token = new MockToken("Token", "TKN", dec); + // Mint enough that huge-magnitude moves succeed, but keep balances below + // int256 max so the test's own int256 delta arithmetic does not overflow. + // int256 max ~5.7e76; keep balances ~ <= 2e76 base units. + uint256 fund = 2 * 10 ** 76; + token.mint(owner, fund); + token.mint(address(harness), fund); + vm.prank(owner); + token.approve(address(harness), type(uint256).max); + } + + /// ATTACK 1: scan pull magnitudes from 1e50 up to the largest that does not + /// overflow uint256 base units, seeding a 0.5 base-unit credit first. At each + /// magnitude assert conservation: realDelta == netRequested + credit, and the + /// solvency bound 0 <= credit < 1 base unit. The hypothesis is that at some + /// magnitude `effective = amount.sub(credit)` silently drops the credit (the + /// add/sub helper ignores operand B when the exponent gap exceeds 76), which + /// would strand the 0.5 base-unit credit -> conservation broken. + function testPullMagnitudeScanConservation() external { + // exponent of the requested token-unit amount. At 6 decimals the base + // unit count is coefficient * 10^(exp+6); must stay < ~1.157e77. + // 1 * 10^exp token units -> 10^(exp+6) base units. exp <= 70 keeps it + // under uint256 max (1e76 base units). exp=71 -> 1e77 base units (still + // < 1.157e77, fits). exp=72 -> 1e78 overflows. + for (int256 exp = 50; exp <= 70; exp++) { + MockToken token = _newToken(6); + + // Seed 0.5 base-unit credit via a 1.5 base-unit pull. + Float r1 = LibDecimalFloat.packLossless(15, -7); + (uint256 moved1,) = harness.exposedPull(owner, address(token), r1); + + Float r2 = LibDecimalFloat.packLossless(1, exp); + (uint256 moved2,) = harness.exposedPull(owner, address(token), r2); + + // Total physically pulled, expressed in token units (Float), built + // from the two uint256 returns so the test never overflows int256. + Float movedTotal = _floatFromBaseUnits(moved1).add(_floatFromBaseUnits(moved2)); + + Float netRequested = r1.add(r2); + Float credit = harness.exposedDustCredit(owner, address(token)); + Float expected = netRequested.add(credit); + + // Conservation: tokens physically pulled == requested + standing credit. + if (!movedTotal.eq(expected)) { + emit log_named_int("PULL BROKEN at exp", exp); + emit log_named_uint("moved1", moved1); + emit log_named_uint("moved2", moved2); + emit log_named_int("movedTotal coeff", _coeff(movedTotal)); + emit log_named_int("movedTotal exp", _exp(movedTotal)); + emit log_named_int("expected coeff", _coeff(expected)); + emit log_named_int("expected exp", _exp(expected)); + emit log_named_int("credit coeff", _coeff(credit)); + emit log_named_int("credit exp", _exp(credit)); + } + assertTrue(movedTotal.eq(expected), "conservation: movedTotal == netRequested + credit"); + assertTrue(!credit.lt(LibDecimalFloat.FLOAT_ZERO), "credit non-negative"); + assertTrue(credit.lt(LibDecimalFloat.packLossless(1, -6)), "credit < 1 base unit"); + } + } + + /// REALISM REGRESSION GUARD (18 decimals): the clamp keeps the orderbook + /// solvent for the common 18-decimal token at every whole-token magnitude + /// whose base unit count fits the funded supply (exp <= 58 keeps 10^(exp+18) + /// <= 2e76). Assert intake >= obligation + standing credit at each. + function testFindMinInsolventExponent18dp() external { + for (int256 exp = 0; exp <= 58; exp++) { + PrecisionAttackMutableDecimalsToken token = new PrecisionAttackMutableDecimalsToken(18); + token.mint(owner, 2 * 10 ** 76); + token.mint(address(harness), 2 * 10 ** 76); + vm.prank(owner); + token.approve(address(harness), type(uint256).max); + + uint256 heldBefore = token.balanceOf(address(harness)); + // seed 0.5 base units credit at 18dp = 5e-19 token units * 1.5 ... use + // 1.5 base units = 15e-19. + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(15, -19)); + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(1, exp)); + uint256 takenIn = token.balanceOf(address(harness)) - heldBefore; + + Float vaultBalance = LibDecimalFloat.packLossless(15, -19).add(LibDecimalFloat.packLossless(1, exp)); + (uint256 obligation,) = LibDecimalFloat.toFixedDecimalLossy(vaultBalance, 18); + Float credit = harness.exposedDustCredit(owner, address(token)); + (uint256 creditBase,) = LibDecimalFloat.toFixedDecimalLossy(credit, 18); + + assertGe(takenIn, obligation + creditBase, "18dp solvent at every whole-token magnitude"); + } + } + + /// A/B vs MAIN: replicate main's pullTokens intake (round-up, no credit) for + /// the same two-pull sequence and compare to the PR harness intake and to the + /// vault obligation at 10^62 token units, the magnitude where the unclamped + /// credit ledger used to under-hold. The precision-loss clamp restores parity: + /// the PR intake is solvent against the obligation just like main. + function testABMainVsPRAtExp62() external { + int256 exp = 62; + + // --- PR harness intake --- + MockToken token = _newToken(6); + uint256 heldBefore = token.balanceOf(address(harness)); + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(15, -7)); + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(1, exp)); + uint256 prTakenIn = token.balanceOf(address(harness)) - heldBefore; + Float prCredit = harness.exposedDustCredit(owner, address(token)); + (uint256 prCreditBase,) = LibDecimalFloat.toFixedDecimalLossy(prCredit, 6); + + // --- main intake replicated inline (round-up per pull, no credit) --- + uint256 mainTakenIn = + _mainPull(LibDecimalFloat.packLossless(15, -7)) + _mainPull(LibDecimalFloat.packLossless(1, exp)); + + // --- vault obligation (Float vault balance -> base units, round down) --- + Float vaultBalance = LibDecimalFloat.packLossless(15, -7).add(LibDecimalFloat.packLossless(1, exp)); + (uint256 obligation,) = LibDecimalFloat.toFixedDecimalLossy(vaultBalance, 6); + + emit log_named_uint("PR takenIn", prTakenIn); + emit log_named_uint("PR credit liability (base)", prCreditBase); + emit log_named_uint("MAIN takenIn", mainTakenIn); + emit log_named_uint("vault obligation", obligation); + + // MAIN is solvent: intake >= obligation. + assertGe(mainTakenIn, obligation, "MAIN: intake >= obligation (solvent)"); + // PR is solvent too: the clamp pulls in at least the vault obligation plus + // the standing credit liability it now also owes the user. + assertGe(prTakenIn, obligation + prCreditBase, "PR: intake >= obligation + credit (solvent)"); + } + + /// main's pullTokens intake: toFixedDecimalLossy rounded UP on lossy. + function _mainPull(Float amount) internal pure returns (uint256 amount18) { + bool lossless; + (amount18, lossless) = LibDecimalFloat.toFixedDecimalLossy(amount, 6); + if (!lossless) { + ++amount18; + } + } + + /// MINIMUM-MAGNITUDE REGRESSION GUARD: the precision-loss clamp keeps the + /// orderbook solvent at every pull magnitude, so no exponent flips a harmless + /// over-hold into an untracked under-hold. Scan every magnitude whose base + /// unit count fits the funded supply (exp <= 70 keeps 10^(exp+6) <= 2e76) and + /// assert intake >= obligation + standing credit at each. + function testFindMinInsolventExponent() external { + for (int256 exp = 0; exp <= 70; exp++) { + MockToken token = _newToken(6); + uint256 heldBefore = token.balanceOf(address(harness)); + + // seed 1.5 base units (-> credit 0.5), then 1*10^exp token units. + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(15, -7)); + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(1, exp)); + uint256 takenIn = token.balanceOf(address(harness)) - heldBefore; + + Float vaultBalance = LibDecimalFloat.packLossless(15, -7).add(LibDecimalFloat.packLossless(1, exp)); + (uint256 obligation,) = LibDecimalFloat.toFixedDecimalLossy(vaultBalance, 6); + Float credit = harness.exposedDustCredit(owner, address(token)); + (uint256 creditBase,) = LibDecimalFloat.toFixedDecimalLossy(credit, 6); + + assertGe(takenIn, obligation + creditBase, "solvent at every pull magnitude"); + } + } + + /// SOLVENCY END-TO-END: compare, for an identical (seed 1.5 base units) + + /// (1e62 token units) two-pull deposit sequence, the orderbook's net token + /// intake against the vault obligation it books, and against the standing + /// credit liability. Solvency requires: + /// heldForUser (real tokens in) + 0 >= vaultObligation - creditLiability + /// equivalently the orderbook must hold at least (vault balance it owes the + /// user) minus (credit it owes the user). A negative slack means the + /// orderbook took in fewer tokens than it now claims to owe -> insolvent. + function testTwoPullSolvencySlack() external { + MockToken token = _newToken(6); + + uint256 heldBefore = token.balanceOf(address(harness)); + + // Two pulls: seed 1.5 base units, then 1e62 token units. + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(15, -7)); + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(1, 62)); + + uint256 heldAfter = token.balanceOf(address(harness)); + uint256 takenIn = heldAfter - heldBefore; // base units the orderbook received + + // Vault obligation in base units the orderbook now owes the user: + // a vault crediting 1.5 + 1e62 token units. When the user withdraws the + // FULL float vault balance, pushTokens converts it to base units (rounded + // down). Compute that exact realizable base-unit obligation. + Float vaultBalance = LibDecimalFloat.packLossless(15, -7).add(LibDecimalFloat.packLossless(1, 62)); + (uint256 obligationBaseUnits,) = LibDecimalFloat.toFixedDecimalLossy(vaultBalance, 6); + + // Standing credit the orderbook ALSO owes the user (base units, rounded + // down for what it could pay). + Float credit = harness.exposedDustCredit(owner, address(token)); + (uint256 creditBaseUnits,) = LibDecimalFloat.toFixedDecimalLossy(credit, 6); + + emit log_named_uint("takenIn (base units)", takenIn); + emit log_named_uint("vault obligation (base units)", obligationBaseUnits); + emit log_named_uint("credit liability (base units)", creditBaseUnits); + + // The orderbook owes the user, on full withdrawal + credit realization, + // at most (obligation + credit) base units; it took in `takenIn`. + // Solvency: takenIn >= obligation + credit (it must hold at least what it + // owes). Report the slack. + uint256 owed = obligationBaseUnits + creditBaseUnits; + emit log_named_uint("owed (obligation+credit)", owed); + if (takenIn < owed) { + emit log_named_uint("INSOLVENT shortfall (base units)", owed - takenIn); + } + assertGe(takenIn, owed, "orderbook holds at least what it owes the user"); + } + + /// DIAGNOSTIC: isolate exp=62 pull. Compare the PR's pulled base units, with + /// and without a seeded 0.5 credit, against the ideal 1e68 base units the + /// vault accounting credits. The solvency-critical question is whether the + /// contract pulls AT LEAST as many base units as the vault is credited + /// (rounding the user's deposit UP for the protocol), or whether the credit + /// machinery causes an UNDER-pull that leaves the vault over-credited. + function testPullExp62SolvencyDiagnostic() external { + // No-seed baseline: a single 1e62 pull. + { + MockToken token = _newToken(6); + (uint256 moved,) = harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(1, 62)); + emit log_named_uint("no-seed moved (base units)", moved); + // Ideal vault-accounting base units for 1e62 token units at 6 dp. + // = 1e68. Solvency requires moved >= 1e68 (pull rounds up). + emit log_named_uint("ideal 1e68", 10 ** 68); + // Does the orderbook receive at least what the vault is credited? + assertGe(moved, 10 ** 68, "no-seed: pulled >= vault-credited (solvent)"); + } + // Seeded 0.5 credit then 1e62 pull. + { + MockToken token = _newToken(6); + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(15, -7)); + (uint256 moved,) = harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(1, 62)); + Float creditAfter = harness.exposedDustCredit(owner, address(token)); + emit log_named_uint("seeded moved (base units)", moved); + emit log_named_int("seeded creditAfter coeff", _coeff(creditAfter)); + emit log_named_int("seeded creditAfter exp", _exp(creditAfter)); + // The vault is credited 1.5 + 1e62 token units across the two pulls + // = 1e68 + 1.5 base units (the 1.5 from the seed). The orderbook + // physically received 2 (seed) + `moved`. Solvency requires + // 2 + moved + creditReleased relationship to hold. Concretely the + // orderbook must hold >= vault total. vault total base units = + // ceil-ish 1e68 + 2 (seed credited 1.5 -> but seed pulled 2). + // Simplest solvency statement at the boundary: total physically held + // for these two pulls (2 + moved) must be >= total vault-credited + // base units (1e68 + ceil(1.5)=2) MINUS the standing credit (which is + // a liability the orderbook owes back). + // total held = 2 + moved ; vault credited (base units) approx 1e68 + 2 + // standing credit (base units) = creditAfter. + // Require: heldBaseUnits + creditAfterBaseUnits >= vaultCreditedBaseUnits + // i.e. orderbook is not under-funded. + // We assert the weaker, decisive check: moved >= 1e68 - 1 (it must not + // fall materially short of the vault-credited 1e68 for the big pull). + emit log_named_uint("shortfall vs 1e68", moved >= 10 ** 68 ? 0 : (10 ** 68 - moved)); + } + } + + /// ATTACK 2: TOFU decimals change between moves. Seed credit at 6 decimals, + /// flip token to 18 decimals, then attempt to realize. If the contract does + /// NOT revert, the stored Float credit could realize at the wrong base-unit + /// scale. Expectation: TOFU forces a revert, neutralizing the attack. + function testDecimalsChangeRevertsAndProtectsCredit() external { + PrecisionAttackMutableDecimalsToken token = new PrecisionAttackMutableDecimalsToken(6); + token.mint(owner, type(uint128).max); + token.mint(address(harness), type(uint128).max); + vm.prank(owner); + token.approve(address(harness), type(uint256).max); + + // First move initializes TOFU at 6 decimals and seeds 0.5 base unit credit. + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(15, -7)); + Float seeded = harness.exposedDustCredit(owner, address(token)); + assertTrue(seeded.eq(LibDecimalFloat.packLossless(5, -7)), "seed credit 0.5"); + + // Token changes decimals to 18. + token.setDecimals(18); + + // Any subsequent pull/push must revert (TOFU Inconsistent), so the stored + // credit can never be realized at the wrong scale. + vm.expectRevert( + abi.encodeWithSelector( + ITOFUTokenDecimals.TokenDecimalsReadFailure.selector, address(token), TOFUOutcome.Inconsistent + ) + ); + harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(15, -7)); + + vm.expectRevert( + abi.encodeWithSelector( + ITOFUTokenDecimals.TokenDecimalsReadFailure.selector, address(token), TOFUOutcome.Inconsistent + ) + ); + harness.exposedPush(owner, address(token), LibDecimalFloat.packLossless(15, -7)); + + // Credit is frozen, unchanged. + assertTrue(harness.exposedDustCredit(owner, address(token)).eq(seeded), "credit frozen after decimals change"); + } + + /// ATTACK 3: high-decimals token (18 dp) sub-unit accumulation. A push of + /// 0.5 base units (5e-19 token units) repeatedly. Confirm the sub-unit + /// crossing math still holds at 18 decimals where the base unit is tiny. + function testHighDecimalsSubUnitAccumulation() external { + MockToken token = _newToken(18); + // 0.5 base units at 18 dp = 5e-19 token units. + Float half = LibDecimalFloat.packLossless(5, -19); + + (uint256 m1,) = harness.exposedPush(owner, address(token), half); + assertEq(m1, 0, "0.5 pushes nothing"); + (uint256 m2,) = harness.exposedPush(owner, address(token), half); + assertEq(m2, 1, "1.0 crosses whole unit"); + assertTrue(harness.exposedDustCredit(owner, address(token)).isZero(), "credit cleared at 18dp"); + } + + /// ATTACK 4: scan push magnitudes. Seed 0.5 base-unit credit (owed to user), + /// then push a huge amount at each magnitude. Conservation for pushes: + /// harnessDelta == -netRequested + credit (the harness sends netRequested and + /// retains the standing credit). If the credit gets dropped in + /// `effective = amount.add(credit)`, the orderbook either over-pays or strands + /// value -> conservation broken. + function testPushMagnitudeScanConservation() external { + for (int256 exp = 50; exp <= 70; exp++) { + MockToken token = _newToken(6); + + Float r1 = LibDecimalFloat.packLossless(15, -7); // rounds down to 1, credit 0.5 + (uint256 moved1,) = harness.exposedPush(owner, address(token), r1); + + Float r2 = LibDecimalFloat.packLossless(1, exp); + (uint256 moved2,) = harness.exposedPush(owner, address(token), r2); + + // Conservation for pushes: tokens physically sent + retained credit + // == requested. i.e. movedTotal + credit == netRequested. + Float movedTotal = _floatFromBaseUnits(moved1).add(_floatFromBaseUnits(moved2)); + Float netRequested = r1.add(r2); + Float credit = harness.exposedDustCredit(owner, address(token)); + Float expected = netRequested.sub(credit); + + if (!movedTotal.eq(expected)) { + emit log_named_int("PUSH BROKEN at exp", exp); + emit log_named_uint("moved1", moved1); + emit log_named_uint("moved2", moved2); + emit log_named_int("movedTotal coeff", _coeff(movedTotal)); + emit log_named_int("movedTotal exp", _exp(movedTotal)); + emit log_named_int("expected coeff", _coeff(expected)); + emit log_named_int("expected exp", _exp(expected)); + emit log_named_int("credit coeff", _coeff(credit)); + emit log_named_int("credit exp", _exp(credit)); + } + assertTrue(movedTotal.eq(expected), "push conservation: movedTotal == netRequested - credit"); + assertTrue(!credit.lt(LibDecimalFloat.FLOAT_ZERO), "credit non-negative"); + assertTrue(credit.lt(LibDecimalFloat.packLossless(1, -6)), "credit < 1 base unit"); + } + } + + /// Converts a base-unit count (6 dp) to a token-unit Float exactly as the + /// contract does, so comparisons are apples-to-apples with the contract's own + /// `pulled`/`pushed` derivation. + function _floatFromBaseUnits(uint256 baseUnits) internal pure returns (Float f) { + (f,) = LibDecimalFloat.fromFixedDecimalLossyPacked(baseUnits, 6); + } + + function _coeff(Float f) internal pure returns (int256 c) { + (c,) = LibDecimalFloat.unpack(f); + } + + function _exp(Float f) internal pure returns (int256 e) { + (, e) = LibDecimalFloat.unpack(f); + } +} diff --git a/test/concrete/raindex/RaindexV6.dustCredit.solvencyAttack.t.sol b/test/concrete/raindex/RaindexV6.dustCredit.solvencyAttack.t.sol new file mode 100644 index 0000000000..892064e145 --- /dev/null +++ b/test/concrete/raindex/RaindexV6.dustCredit.solvencyAttack.t.sol @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Test} from "forge-std-1.16.1/src/Test.sol"; +import {Float, LibDecimalFloat} from "rain-math-float-0.1.1/src/lib/LibDecimalFloat.sol"; +import {MockToken} from "test/util/concrete/MockToken.sol"; +import {LibRainDeploy} from "rain-deploy-0.1.2/src/lib/LibRainDeploy.sol"; +import {LibTOFUTokenDecimals} from "rain-tofu-erc20-decimals-0.1.1/src/lib/LibTOFUTokenDecimals.sol"; +import { + RaindexV6DustCreditSolvencyAttackHarness +} from "test/concrete/raindex/RaindexV6DustCreditSolvencyAttackHarness.sol"; + +/// @title Adversarial solvency attack on the dust-credit ledger. +/// @notice Tries to construct a sequence where realizing a credit pays out +/// tokens the orderbook does not hold for that user (draining a pooled balance / +/// a third party), or where a credit is backed by nothing. +contract RaindexV6DustCreditSolvencyAttackTest is Test { + using LibDecimalFloat for Float; + + RaindexV6DustCreditSolvencyAttackHarness internal harness; + address internal alice = makeAddr("alice"); + address internal bob = makeAddr("bob"); + + function _deployHarness() internal { + LibRainDeploy.etchZoltuFactory(vm); + LibRainDeploy.deployZoltu(LibTOFUTokenDecimals.TOFU_DECIMALS_EXPECTED_CREATION_CODE); + harness = RaindexV6DustCreditSolvencyAttackHarness( + payable(address(uint160(uint256(keccak256("dust.credit.solvency.attack"))))) + ); + vm.etch(address(harness), type(RaindexV6DustCreditSolvencyAttackHarness).runtimeCode); + } + + function _token(uint8 decimals) internal returns (MockToken token) { + token = new MockToken("Token", "TKN", decimals); + // Mint a huge but bounded supply so big transfers don't run out of + // balance: the point of these tests is the credit math, not ERC20 limits. + uint256 supply = type(uint256).max / 4; + token.mint(alice, supply); + token.mint(bob, supply); + token.mint(address(harness), supply); + vm.prank(alice); + token.approve(address(harness), type(uint256).max); + vm.prank(bob); + token.approve(address(harness), type(uint256).max); + } + + /// Cross-account pooled solvency. Two users churn pulls and pushes for the + /// SAME token against ONE pooled real balance. After every move the global + /// solvency identity must hold: + /// realDelta == netRequested(alice) + netRequested(bob) + /// + credit(alice) + credit(bob) + /// and each credit stays in [0, 1 base unit). If two users' credits ever + /// double-counted the same real balance, this identity would break (real + /// would fall short of the obligations). + /// forge-config: default.fuzz.runs = 4000 + function testCrossAccountPooledSolvency(uint8[] memory moves, uint8[] memory units) external { + _deployHarness(); + MockToken token = _token(6); + + vm.assume(moves.length > 0 && units.length > 0); + uint256 n = moves.length < units.length ? moves.length : units.length; + + int256 startReal = int256(token.balanceOf(address(harness))); + // net requested per user in tenths of a base unit (exact integer math). + int256 netAliceTenths = 0; + int256 netBobTenths = 0; + + Float oneBaseUnit = LibDecimalFloat.packLossless(1, -6); + + for (uint256 i = 0; i < n; i++) { + uint8 m = moves[i]; + uint256 u = units[i]; + Float amount = LibDecimalFloat.packLossless(int256(u), -7); + // 2 low bits select account+direction: 00 alice pull, 01 alice push, + // 10 bob pull, 11 bob push. + address who = (m & 2) == 0 ? alice : bob; + bool isPull = (m & 1) == 0; + + if (isPull) { + harness.exposedPull(who, address(token), amount); + if (who == alice) netAliceTenths += int256(u); + else netBobTenths += int256(u); + } else { + harness.exposedPush(who, address(token), amount); + if (who == alice) netAliceTenths -= int256(u); + else netBobTenths -= int256(u); + } + + _checkPooled(token, startReal, netAliceTenths, netBobTenths, oneBaseUnit); + } + } + + function _checkPooled( + MockToken token, + int256 startReal, + int256 netAliceTenths, + int256 netBobTenths, + Float oneBaseUnit + ) internal view { + int256 realDeltaBaseUnits = int256(token.balanceOf(address(harness))) - startReal; + Float realDelta = LibDecimalFloat.packLossless(realDeltaBaseUnits, -6); + + Float creditAlice = harness.exposedDustCredit(alice, address(token)); + Float creditBob = harness.exposedDustCredit(bob, address(token)); + + Float netAlice = LibDecimalFloat.packLossless(netAliceTenths, -7); + Float netBob = LibDecimalFloat.packLossless(netBobTenths, -7); + + Float expected = netAlice.add(netBob).add(creditAlice).add(creditBob); + assertTrue(realDelta.eq(expected), "global pooled solvency identity"); + + // Solvency bounds on each per-user credit. + assertTrue(!creditAlice.lt(LibDecimalFloat.FLOAT_ZERO), "alice credit >= 0"); + assertTrue(creditAlice.lt(oneBaseUnit), "alice credit < 1 base unit"); + assertTrue(!creditBob.lt(LibDecimalFloat.FLOAT_ZERO), "bob credit >= 0"); + assertTrue(creditBob.lt(oneBaseUnit), "bob credit < 1 base unit"); + } + + /// Same-token same-tx arrive-and-leave, mirroring clear3: token X is pulled + /// from alice (over-pull, +credit alice) and pushed to bob (under-push, + /// +credit bob) in the same logical clear. Verify neither credit is backed by + /// the other's tokens: realDelta must equal netRequested + both credits. + function testArriveAndLeaveSameTxSameToken() external { + _deployHarness(); + MockToken token = _token(6); + + int256 startReal = int256(token.balanceOf(address(harness))); + + // alice's vault-0 output of 1.5 base units -> pulled, rounds up to 2. + Float aliceOut = LibDecimalFloat.packLossless(15, -7); + // bob's vault-0 input of 1.5 base units -> pushed, rounds down to 1. + Float bobIn = LibDecimalFloat.packLossless(15, -7); + + // clear3 ordering: pull outputs first, then push inputs. + (uint256 pulled,) = harness.exposedPull(alice, address(token), aliceOut); + (uint256 pushed,) = harness.exposedPush(bob, address(token), bobIn); + + assertEq(pulled, 2, "alice over-pull rounds up"); + assertEq(pushed, 1, "bob under-push rounds down"); + + int256 realDelta = int256(token.balanceOf(address(harness))) - startReal; + // Net real: +2 (from alice) -1 (to bob) = +1 base unit. + assertEq(realDelta, 1, "net real +1"); + + Float creditAlice = harness.exposedDustCredit(alice, address(token)); + Float creditBob = harness.exposedDustCredit(bob, address(token)); + // alice credit 0.5 (over-pull), bob credit 0.5 (under-push). + assertTrue(creditAlice.eq(LibDecimalFloat.packLossless(5, -7)), "alice credit 0.5"); + assertTrue(creditBob.eq(LibDecimalFloat.packLossless(5, -7)), "bob credit 0.5"); + + // Global identity: realDelta(token units) == netRequested + credits. + // netRequested = +1.5 (alice pull) - 1.5 (bob push) = 0. + Float realDeltaF = LibDecimalFloat.packLossless(realDelta, -6); + Float expected = creditAlice.add(creditBob); // net requested == 0 + assertTrue(realDeltaF.eq(expected), "arrive-and-leave solvency identity"); + } + + /// Large-amount precision attack on PUSH. A huge push amount whose integer + /// transfer exceeds ~67 significant digits could make `pushed` (the Float + /// round-trip of the integer) smaller than the integer actually sent, + /// inflating the recorded credit beyond what was withheld -> a credit backed + /// by nothing. We push amounts spanning the full uint256 magnitude range + /// (mantissa * 10^expDigits base units) and assert the recorded credit equals + /// the TRUE withheld dust (requestedTokenUnits - sentTokenUnits), and stays in + /// [0, 1 base unit). If the lossy round-trip inflated the credit, this breaks. + /// forge-config: default.fuzz.runs = 5000 + function testLargeAmountPushCreditNotInflated(uint256 mantissa, uint8 expDigits, uint8 decimals) external { + decimals = uint8(bound(decimals, 0, 36)); + // mantissa fits in int224 (<= ~66 digits) so our own assertion-side + // packLossless never overflows; expDigits supplies the extra magnitude. + mantissa = bound(mantissa, 1, uint256(uint224(type(int224).max))); + // Keep mantissa * 10^expDigits within the minted supply (uint256.max/4). + expDigits = uint8(bound(expDigits, 0, 70)); + _deployHarness(); + MockToken token = _token(decimals); + + Float oneBaseUnit = LibDecimalFloat.packLossless(1, -int256(uint256(decimals))); + + // value = mantissa * 10^expDigits base units. Ensure it fits in supply. + uint256 maxMantissa = (type(uint256).max / 4) / (10 ** uint256(expDigits)); + if (maxMantissa == 0) return; + if (mantissa > maxMantissa) mantissa = maxMantissa; + if (mantissa == 0) return; + + // requested in TOKEN units = mantissa * 10^(expDigits - decimals). + Float requested = + LibDecimalFloat.packLossless(int256(mantissa), int256(uint256(expDigits)) - int256(uint256(decimals))); + + uint256 balBefore = token.balanceOf(address(harness)); + (uint256 sent,) = harness.exposedPush(alice, address(token), requested); + + // The orderbook never sends out more than it held. + assertLe(sent, balBefore, "never sends more than held"); + + Float credit = harness.exposedDustCredit(alice, address(token)); + assertTrue(!credit.lt(LibDecimalFloat.FLOAT_ZERO), "post-big credit >= 0"); + assertTrue(credit.lt(oneBaseUnit), "post-big credit < 1 base unit"); + + // Core solvency check: the recorded credit must not exceed the TRUE + // withheld dust = requested - sent (token units). If a lossy round-trip + // inflated `credit` above the real shortfall, the orderbook would be + // recording a debt it never withheld -> a credit backed by nothing. + // `sent` can exceed int224; pack it lossily and use >= so any inflation + // of `credit` beyond the real (possibly under-counted) shortfall trips. + (Float sentTokenUnits,) = LibDecimalFloat.fromFixedDecimalLossyPacked(sent, decimals); + Float trueWithheld = requested.sub(sentTokenUnits); + // credit must be <= trueWithheld (never inflated above what was withheld). + assertTrue(!credit.gt(trueWithheld), "credit <= true withheld dust (not inflated)"); + } + + /// Direct seed-then-drain attack: can an accumulated push credit ever pay out + /// tokens that were not actually withheld? Build up credit to just under a + /// base unit, then realize it, and confirm the realized base unit was indeed + /// covered by tokens previously NOT sent (i.e. total sent over the whole + /// sequence equals floor(total requested + 0) exactly, never more). + function testPushNeverPaysMoreThanRequestedPlusWithheld() external { + _deployHarness(); + MockToken token = _token(6); + + // Request 0.9 base units nine times = 8.1 base units total requested. + // floor accounting: cumulative sent must always equal + // floor(cumulativeRequested) and never exceed it. + Float amount = LibDecimalFloat.packLossless(9, -7); // 0.9 base units + uint256 totalSent = 0; + // requested cumulative in tenths of a base unit. + uint256 reqTenths = 0; + for (uint256 k = 0; k < 12; k++) { + (uint256 sent,) = harness.exposedPush(alice, address(token), amount); + totalSent += sent; + reqTenths += 9; + // Invariant: never sent more than the whole-base-units requested. + assertLe(totalSent, reqTenths / 10, "never over-pays cumulatively"); + // And the shortfall is exactly the standing credit. + Float credit = harness.exposedDustCredit(alice, address(token)); + // requested - sent (token units) must equal credit. + Float requested = LibDecimalFloat.packLossless(int256(reqTenths), -7); + Float sentF = LibDecimalFloat.packLossless(int256(totalSent), -6); + assertTrue(requested.sub(sentF).eq(credit), "withheld == credit exactly"); + } + } +} diff --git a/test/concrete/raindex/RaindexV6.dustCredit.t.sol b/test/concrete/raindex/RaindexV6.dustCredit.t.sol new file mode 100644 index 0000000000..d024bda536 --- /dev/null +++ b/test/concrete/raindex/RaindexV6.dustCredit.t.sol @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Test} from "forge-std-1.16.1/src/Test.sol"; +import {Float, LibDecimalFloat} from "rain-math-float-0.1.1/src/lib/LibDecimalFloat.sol"; +import {MockToken} from "test/util/concrete/MockToken.sol"; +import {LibRainDeploy} from "rain-deploy-0.1.2/src/lib/LibRainDeploy.sol"; +import {LibTOFUTokenDecimals} from "rain-tofu-erc20-decimals-0.1.1/src/lib/LibTOFUTokenDecimals.sol"; +import {RaindexV6DustCreditHarness} from "test/concrete/raindex/RaindexV6DustCreditHarness.sol"; + +/// @title RaindexV6DustCreditTest +/// @notice L01 follow-up (#2673): every lossy float->fixed-decimal token move +/// leaves a sub-base-unit remainder. `pullTokens` rounds the transfer UP (the +/// orderbook receives the excess) and `pushTokens` rounds it DOWN (the orderbook +/// keeps the shortfall); in both cases the residue is real tokens the orderbook +/// holds on behalf of `account`. Rather than stranding it, the residue is booked +/// into `sDustCredit[account][token]` (token units) and realized into the next +/// move for the same `(account, token)`. +/// +/// The solvency invariant is paramount: the orderbook's real token balance must +/// always cover every vault obligation plus every tracked credit, and a credit +/// can only ever release tokens the orderbook provably already holds for that +/// user, so no move can over-credit or dip into a vault balance. The conservation +/// invariant exercised throughout is, in token units: +/// +/// realBalanceDelta == netRequested + credit +/// +/// where `netRequested` is the sum of requested pull amounts minus push amounts +/// (the exact economic value the vault accounting moved) and `credit` is the +/// standing ledger entry. It holds exactly after every move. +contract RaindexV6DustCreditTest is Test { + using LibDecimalFloat for Float; + + RaindexV6DustCreditHarness internal harness; + address internal owner = makeAddr("owner"); + // 6-decimal token: one base unit is 1e-6 token units. + MockToken internal token; + + function setUp() external { + // pullTokens/pushTokens read token decimals via the deployed TOFU + // contract, so it must exist before any move. + LibRainDeploy.etchZoltuFactory(vm); + LibRainDeploy.deployZoltu(LibTOFUTokenDecimals.TOFU_DECIMALS_EXPECTED_CREATION_CODE); + + // Etch the runtime code so the large RaindexV6-derived harness isn't + // subject to the EIP-170 creation size limit. + harness = RaindexV6DustCreditHarness(payable(address(uint160(uint256(keccak256("dust.credit.harness")))))); + vm.etch(address(harness), type(RaindexV6DustCreditHarness).runtimeCode); + + token = new MockToken("Token", "TKN", 6); + // Both sides are funded generously so transfers never fail for lack of + // balance/approval; the tests assert exact deltas, not absolute balances. + token.mint(owner, 1e18); + token.mint(address(harness), 1e18); + vm.prank(owner); + token.approve(address(harness), type(uint256).max); + } + + /// At rest the ledger is empty. + function testDustCreditStartsZero() external view { + assertTrue(harness.exposedDustCredit(owner, address(token)).isZero(), "credit starts zero"); + } + + /// Two consecutive pulls of 1.5 base units. The first is lossy and rounds the + /// transfer up to 2, booking 0.5 base units of credit. The second consumes + /// that credit: it only needs to pull 1.0 base unit (lossless), so exactly 1 + /// is transferred and the ledger returns to zero. Total moved is 3 base units + /// for 3.0 requested - the round-up dust is recovered, not stranded. + /// Pins the realize-into-next-pull path: a mutation that ignores the standing + /// credit pulls 2 again on the second move (4 total) and leaves a stale + /// credit. + function testPullRealizesCreditIntoNextPull() external { + // 1.5 base units = 15e-7 token units. + Float amount = LibDecimalFloat.packLossless(15, -7); + + (uint256 moved1,) = harness.exposedPull(owner, address(token), amount); + assertEq(moved1, 2, "first pull rounds up to 2"); + // Credit is 2 - 1.5 = 0.5 base units = 5e-7 token units. + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(5, -7)), "credit 0.5" + ); + + (uint256 moved2,) = harness.exposedPull(owner, address(token), amount); + assertEq(moved2, 1, "second pull consumes credit and moves only 1"); + assertTrue(harness.exposedDustCredit(owner, address(token)).isZero(), "credit cleared"); + + // Exactly 3 base units moved into the harness for 3.0 requested. + assertEq(moved1 + moved2, 3, "exact conservation across two pulls"); + } + + /// Two consecutive pushes of 1.5 base units. The first rounds the transfer + /// down to 1, booking 0.5 base units of credit (owed to the user). The second + /// realizes it: 1.5 + 0.5 = 2.0 base units, so exactly 2 are transferred and + /// the ledger returns to zero. Total moved is 3 base units for 3.0 owed - the + /// round-down dust is paid out, not stranded. + /// Pins the realize-into-next-push path: a mutation that ignores the standing + /// credit pushes 1 again on the second move (2 total) and leaves a stale + /// credit. + function testPushRealizesCreditIntoNextPush() external { + Float amount = LibDecimalFloat.packLossless(15, -7); + + (uint256 moved1,) = harness.exposedPush(owner, address(token), amount); + assertEq(moved1, 1, "first push rounds down to 1"); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(5, -7)), "credit 0.5" + ); + + (uint256 moved2,) = harness.exposedPush(owner, address(token), amount); + assertEq(moved2, 2, "second push realizes the whole-unit credit"); + assertTrue(harness.exposedDustCredit(owner, address(token)).isZero(), "credit cleared"); + + assertEq(moved1 + moved2, 3, "exact conservation across two pushes"); + } + + /// Sub-base-unit pushes accumulate until they cross a whole base unit. Three + /// pushes of 0.4 base units each: 0.4 -> 0.8 -> 1.2. Only the third move + /// transfers a token (1 base unit), leaving 0.2 base units of credit. The + /// orderbook never over-pays: it pays a whole unit only once the owed + /// fraction has provably accumulated past one. + /// Pins the sub-unit accumulation crossing a whole unit: a mutation that + /// resets the credit each move never reaches the boundary and transfers 0 + /// three times. + function testPushAccumulatesSubUnitToWholeUnit() external { + // 0.4 base units = 4e-7 token units. + Float amount = LibDecimalFloat.packLossless(4, -7); + + (uint256 moved1,) = harness.exposedPush(owner, address(token), amount); + assertEq(moved1, 0, "0.4 pushes nothing"); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(4, -7)), "credit 0.4" + ); + + (uint256 moved2,) = harness.exposedPush(owner, address(token), amount); + assertEq(moved2, 0, "0.8 pushes nothing"); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(8, -7)), "credit 0.8" + ); + + (uint256 moved3,) = harness.exposedPush(owner, address(token), amount); + assertEq(moved3, 1, "1.2 crosses a whole unit, pushes 1"); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(2, -7)), "credit 0.2" + ); + } + + /// A pull whose amount is smaller than the standing credit moves no tokens at + /// all and only shrinks the credit. First a 1.5 base-unit pull books 0.5 base + /// units of credit; then a 0.3 base-unit pull is fully covered by that credit, + /// so nothing is pulled and the credit drops to 0.2 base units. This is the + /// conservative "credit covers the whole pull" branch. + /// Pins the no-transfer credit-shrink path: a mutation that always pulls at + /// least one base unit (ignoring the covering credit) moves a token here and + /// over-charges the owner. + function testPullCoveredEntirelyByCredit() external { + // Seed 0.5 base units of credit with a 1.5 base-unit pull. + (uint256 seeded,) = harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(15, -7)); + assertEq(seeded, 2, "seed pull moves 2"); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(5, -7)), "seed credit 0.5" + ); + + uint256 ownerBefore = token.balanceOf(owner); + // 0.3 base units < 0.5 credit, so no tokens move. + (uint256 moved,) = harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(3, -7)); + assertEq(moved, 0, "covered pull moves nothing"); + assertEq(token.balanceOf(owner), ownerBefore, "owner balance unchanged"); + // Credit shrinks by the requested 0.3 to 0.2 base units. + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(2, -7)), "credit 0.2" + ); + } + + /// A push that realizes accumulated credit DOES pay an extra base unit out of + /// the orderbook. Seed 0.8 base units of credit (two 0.4 pushes), then a push + /// of 0.5 base units: 0.5 + 0.8 = 1.3, so the orderbook transfers 1 base unit + /// it would otherwise have truncated away, and 0.3 base units of credit + /// remain. Confirms credit can only ADD to a push (never subtract), keeping it + /// solvent. + function testPushCreditAddsExtraUnit() external { + harness.exposedPush(owner, address(token), LibDecimalFloat.packLossless(4, -7)); + harness.exposedPush(owner, address(token), LibDecimalFloat.packLossless(4, -7)); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(8, -7)), "credit 0.8" + ); + + uint256 ownerBefore = token.balanceOf(owner); + // 0.5 + 0.8 = 1.3 base units -> transfer 1, keep 0.3. + (uint256 moved,) = harness.exposedPush(owner, address(token), LibDecimalFloat.packLossless(5, -7)); + assertEq(moved, 1, "0.5 push with 0.8 credit transfers a realized unit"); + assertEq(token.balanceOf(owner) - ownerBefore, 1, "owner received exactly 1 base unit"); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(3, -7)), "credit 0.3" + ); + } + + /// A lossless move never touches the ledger. A 3-base-unit pull (3e-6, exact + /// at 6 decimals) transfers exactly 3 and leaves the credit at zero. Pins that + /// the ledger is only written when there is a genuine remainder. + function testLosslessMoveLeavesCreditZero() external { + (uint256 moved,) = harness.exposedPull(owner, address(token), LibDecimalFloat.packLossless(3, -6)); + assertEq(moved, 3, "lossless pull moves exactly 3"); + assertTrue(harness.exposedDustCredit(owner, address(token)).isZero(), "lossless leaves credit zero"); + } + + /// The credit ledger is keyed per `(user, token)`: a remainder accrued for one + /// user is never visible to or realized by another. Two different owners each + /// pulling 1.5 base units both round up independently to 2 and each carry their + /// own 0.5 base-unit credit. Pins the mapping key so a mutation collapsing the + /// ledger to a single global slot is caught. + function testCreditIsolatedPerUser() external { + address other = makeAddr("other"); + token.mint(other, 1e18); + vm.prank(other); + token.approve(address(harness), type(uint256).max); + + Float amount = LibDecimalFloat.packLossless(15, -7); + (uint256 movedOwner,) = harness.exposedPull(owner, address(token), amount); + (uint256 movedOther,) = harness.exposedPull(other, address(token), amount); + + assertEq(movedOwner, 2, "owner rounds up independently"); + assertEq(movedOther, 2, "other rounds up independently"); + assertTrue( + harness.exposedDustCredit(owner, address(token)).eq(LibDecimalFloat.packLossless(5, -7)), "owner credit" + ); + assertTrue( + harness.exposedDustCredit(other, address(token)).eq(LibDecimalFloat.packLossless(5, -7)), "other credit" + ); + } + + /// Fuzz: an arbitrary sequence of pulls and pushes preserves the conservation + /// and solvency invariants after EVERY move. + /// + /// - Conservation (exact): the harness's real token-balance delta in token + /// units equals `netRequested + credit`. Every base unit that physically + /// moved is accounted for by the requested economic value plus the standing + /// credit - no dust is created or destroyed. + /// - Solvency: the credit is always non-negative and strictly less than one + /// base unit, so the orderbook can never over-credit (a credit is always + /// backed by real tokens it already holds) and never strands a whole base + /// unit it should have realized. + /// forge-config: default.fuzz.runs = 2000 + function testConservationAndSolvencyInvariant(bool[] memory isPull, uint8[] memory units) external { + vm.assume(isPull.length > 0); + uint256 n = isPull.length < units.length ? isPull.length : units.length; + vm.assume(n > 0); + + // One base unit is 1e-6 token units at 6 decimals. + Float oneBaseUnit = LibDecimalFloat.packLossless(1, -6); + + int256 harnessStart = int256(token.balanceOf(address(harness))); + // netRequested is tracked in tenths of a base unit (each move is units/10 + // base units) to stay in exact integer arithmetic; compared as a Float. + int256 netRequestedTenths = 0; + + for (uint256 i = 0; i < n; i++) { + // Each move is between 0.0 and 25.5 base units (units/10), spanning + // sub-unit, whole, and mixed magnitudes. + uint256 u = units[i]; + // requested amount in token units: u * 1e-7 (u tenths of a base unit). + Float amount = LibDecimalFloat.packLossless(int256(u), -7); + + if (isPull[i]) { + harness.exposedPull(owner, address(token), amount); + netRequestedTenths += int256(u); + } else { + harness.exposedPush(owner, address(token), amount); + netRequestedTenths -= int256(u); + } + + // Conservation: realBalanceDelta == netRequested + credit (token units). + int256 harnessDeltaBaseUnits = int256(token.balanceOf(address(harness))) - harnessStart; + Float realDelta = LibDecimalFloat.packLossless(harnessDeltaBaseUnits, -6); + Float credit = harness.exposedDustCredit(owner, address(token)); + Float netRequested = LibDecimalFloat.packLossless(netRequestedTenths, -7); + assertTrue(realDelta.eq(netRequested.add(credit)), "conservation: realDelta == netRequested + credit"); + + // Solvency: 0 <= credit < 1 base unit. + assertTrue(!credit.lt(LibDecimalFloat.FLOAT_ZERO), "credit non-negative"); + assertTrue(credit.lt(oneBaseUnit), "credit under one base unit"); + } + } +} diff --git a/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol index 19b3f543b2..4e9365e755 100644 --- a/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol +++ b/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol @@ -85,7 +85,15 @@ contract RaindexV6TakeOrderPrecisionTest is RaindexV6ExternalRealTest { { (uint256 absoluteTakerInputAmount, bool lossless) = expectedTakerTotalInput.toFixedDecimalLossy(outputTokenDecimals); - (lossless); + // When the output vault is non-zero the taker is also the depositor, + // so the lossy seed deposit above over-pulled by `ceil - exact` and + // booked it as dust credit for `(this, outputToken)`. The matching + // push to the taker realizes that credit, sending `floor(exact + + // credit) == ceil` rather than the truncated `floor(exact)`. A vault-0 + // output has no seed deposit so the push is the plain truncation. + if (!lossless && outputVaultId != bytes32(0)) { + ++absoluteTakerInputAmount; + } vm.mockCall( outputToken, abi.encodeWithSelector(IERC20.transfer.selector, address(this), absoluteTakerInputAmount), @@ -109,7 +117,16 @@ contract RaindexV6TakeOrderPrecisionTest is RaindexV6ExternalRealTest { } if (inputVaultId == bytes32(0)) { - (uint256 absoluteInputAmount,) = expectedTakerTotalOutput.toFixedDecimalLossy(inputTokenDecimals); + // The vault-0 input is pushed back out to the owner, who is also the + // taker here. The taker payment pull above over-pulled by `ceil - + // exact` and booked it as dust credit for `(this, inputToken)`, so the + // vault-0 push realizes that credit and sends `floor(exact + credit) + // == ceil` rather than the truncated `floor(exact)`. + (uint256 absoluteInputAmount, bool lossless) = + expectedTakerTotalOutput.toFixedDecimalLossy(inputTokenDecimals); + if (!lossless) { + ++absoluteInputAmount; + } mockVault0Input(inputToken, address(this), absoluteInputAmount); } diff --git a/test/concrete/raindex/RaindexV6.withdraw.entask.t.sol b/test/concrete/raindex/RaindexV6.withdraw.entask.t.sol index aa2536e577..b5fe6ae67e 100644 --- a/test/concrete/raindex/RaindexV6.withdraw.entask.t.sol +++ b/test/concrete/raindex/RaindexV6.withdraw.entask.t.sol @@ -28,7 +28,8 @@ contract RaindexV6WithdrawEvalTest is RaindexV6ExternalRealTest { function checkReentrancyRW(uint256 expectedReads, uint256 expectedWrites) internal view { (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // 3 reads for reentrancy guard. - // 2 reads for deposit. + // 2 reads for the vault balance Float. + // 2 reads for the sDustCredit Float that pushTokens loads. assertEq(reads.length, expectedReads, "reads length"); // ReentrancyGuard.REENTRANCY_GUARD_STORAGE bytes32 reentrancyGuardStorage = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; @@ -36,7 +37,8 @@ contract RaindexV6WithdrawEvalTest is RaindexV6ExternalRealTest { assertEq(reads[1], reentrancyGuardStorage, "reads[1]"); assertEq(reads[reads.length - 1], reentrancyGuardStorage, "reads[reads.length - 1]"); // 2 writes for reentrancy guard. - // 1 write for deposit. + // 1 write for the vault balance. + // 1 write for the sDustCredit slot that pushTokens stores back. assertEq(writes.length, expectedWrites, "writes length"); assertEq(writes[0], reentrancyGuardStorage, "writes[0]"); assertEq(writes[writes.length - 1], reentrancyGuardStorage, "writes[writes.length - 1]"); @@ -117,7 +119,7 @@ contract RaindexV6WithdrawEvalTest is RaindexV6ExternalRealTest { } iRaindex.withdraw4(address(iToken0), vaultId, targetAmount, actions); if (err.length == 0) { - checkReentrancyRW(6, 3); + checkReentrancyRW(8, 4); (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iStore)); assertEq(reads.length, expectedReads); assertEq(writes.length, expectedWrites); diff --git a/test/concrete/raindex/RaindexV6.withdraw.t.sol b/test/concrete/raindex/RaindexV6.withdraw.t.sol index c093e2ab8d..0762ccae99 100644 --- a/test/concrete/raindex/RaindexV6.withdraw.t.sol +++ b/test/concrete/raindex/RaindexV6.withdraw.t.sol @@ -56,8 +56,11 @@ contract RaindexV6WithdrawTest is RaindexV6ExternalMockTest { vm.record(); iRaindex.withdraw4(address(iToken0), vaultId, amount, new TaskV2[](0)); (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); - assertEq(reads.length, 6, "reads"); - assertEq(writes.length, 3, "writes"); + // The noop withdraw still calls pushTokens, which reads sDustCredit (2 + // SLOADs of the Float slot) and unconditionally writes it back (1 SSTORE), + // adding 2 reads and 1 write over the pre-dust-credit 6 reads / 3 writes. + assertEq(reads.length, 8, "reads"); + assertEq(writes.length, 4, "writes"); } /// Withdrawing the full amount from a vault should delete the vault. diff --git a/test/concrete/raindex/RaindexV6DustCreditConservationAttackHarness.sol b/test/concrete/raindex/RaindexV6DustCreditConservationAttackHarness.sol new file mode 100644 index 0000000000..9cfac6ff66 --- /dev/null +++ b/test/concrete/raindex/RaindexV6DustCreditConservationAttackHarness.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {RaindexV6} from "src/concrete/raindex/RaindexV6.sol"; +import {Float} from "rain-math-float-0.1.1/src/lib/LibDecimalFloat.sol"; + +contract RaindexV6DustCreditConservationAttackHarness is RaindexV6 { + function exposedPull(address account, address token, Float amount) external returns (uint256, uint8) { + return pullTokens(account, token, amount); + } + + function exposedPush(address account, address token, Float amount) external returns (uint256, uint8) { + return pushTokens(account, token, amount); + } + + function exposedDustCredit(address user, address token) external view returns (Float) { + return sDustCredit[user][token]; + } +} diff --git a/test/concrete/raindex/RaindexV6DustCreditHarness.sol b/test/concrete/raindex/RaindexV6DustCreditHarness.sol new file mode 100644 index 0000000000..ff77c0ba26 --- /dev/null +++ b/test/concrete/raindex/RaindexV6DustCreditHarness.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {RaindexV6} from "src/concrete/raindex/RaindexV6.sol"; +import {Float} from "rain-math-float-0.1.1/src/lib/LibDecimalFloat.sol"; + +contract RaindexV6DustCreditHarness is RaindexV6 { + function exposedPull(address account, address token, Float amount) external returns (uint256, uint8) { + return pullTokens(account, token, amount); + } + + function exposedPush(address account, address token, Float amount) external returns (uint256, uint8) { + return pushTokens(account, token, amount); + } + + function exposedDustCredit(address user, address token) external view returns (Float) { + return sDustCredit[user][token]; + } +} diff --git a/test/concrete/raindex/RaindexV6DustCreditPrecisionAttackHarness.sol b/test/concrete/raindex/RaindexV6DustCreditPrecisionAttackHarness.sol new file mode 100644 index 0000000000..c727a2416e --- /dev/null +++ b/test/concrete/raindex/RaindexV6DustCreditPrecisionAttackHarness.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {RaindexV6} from "src/concrete/raindex/RaindexV6.sol"; +import {Float} from "rain-math-float-0.1.1/src/lib/LibDecimalFloat.sol"; + +contract RaindexV6DustCreditPrecisionAttackHarness is RaindexV6 { + function exposedPull(address account, address token, Float amount) external returns (uint256, uint8) { + return pullTokens(account, token, amount); + } + + function exposedPush(address account, address token, Float amount) external returns (uint256, uint8) { + return pushTokens(account, token, amount); + } + + function exposedDustCredit(address user, address token) external view returns (Float) { + return sDustCredit[user][token]; + } +} diff --git a/test/concrete/raindex/RaindexV6DustCreditSolvencyAttackHarness.sol b/test/concrete/raindex/RaindexV6DustCreditSolvencyAttackHarness.sol new file mode 100644 index 0000000000..2d5c7550e8 --- /dev/null +++ b/test/concrete/raindex/RaindexV6DustCreditSolvencyAttackHarness.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {RaindexV6} from "src/concrete/raindex/RaindexV6.sol"; +import {Float} from "rain-math-float-0.1.1/src/lib/LibDecimalFloat.sol"; + +contract RaindexV6DustCreditSolvencyAttackHarness is RaindexV6 { + function exposedPull(address account, address token, Float amount) external returns (uint256, uint8) { + return pullTokens(account, token, amount); + } + + function exposedPush(address account, address token, Float amount) external returns (uint256, uint8) { + return pushTokens(account, token, amount); + } + + function exposedDustCredit(address user, address token) external view returns (Float) { + return sDustCredit[user][token]; + } +}