diff --git a/.gitignore b/.gitignore index 32b4668..df4e30d 100644 --- a/.gitignore +++ b/.gitignore @@ -98,6 +98,9 @@ typings/ *.swp *.swo +# Backup files +*.bak + # OS .DS_Store Thumbs.db diff --git a/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.dbg.json b/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.dbg.json index c3701af..bdd44d0 100644 --- a/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.dbg.json +++ b/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/169ec88754f8ab831077ca9fbb049cf4.json" + "buildInfo": "../../../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.dbg.json b/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.dbg.json index c3701af..bdd44d0 100644 --- a/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.dbg.json +++ b/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/169ec88754f8ab831077ca9fbb049cf4.json" + "buildInfo": "../../../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.dbg.json b/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.dbg.json index c3701af..bdd44d0 100644 --- a/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.dbg.json +++ b/backend/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/169ec88754f8ab831077ca9fbb049cf4.json" + "buildInfo": "../../../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json b/backend/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json index 68fcf57..d797b83 100644 --- a/backend/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json +++ b/backend/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../../build-info/169ec88754f8ab831077ca9fbb049cf4.json" + "buildInfo": "../../../../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json b/backend/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json index 68fcf57..d797b83 100644 --- a/backend/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json +++ b/backend/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../../build-info/169ec88754f8ab831077ca9fbb049cf4.json" + "buildInfo": "../../../../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json b/backend/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json index 862e7fd..c060b08 100644 --- a/backend/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json +++ b/backend/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../../../build-info/169ec88754f8ab831077ca9fbb049cf4.json" + "buildInfo": "../../../../../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json b/backend/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json index c3701af..bdd44d0 100644 --- a/backend/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json +++ b/backend/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/169ec88754f8ab831077ca9fbb049cf4.json" + "buildInfo": "../../../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/@openzeppelin/contracts/utils/ReentrancyGuard.sol/ReentrancyGuard.dbg.json b/backend/artifacts/@openzeppelin/contracts/utils/ReentrancyGuard.sol/ReentrancyGuard.dbg.json index c3701af..bdd44d0 100644 --- a/backend/artifacts/@openzeppelin/contracts/utils/ReentrancyGuard.sol/ReentrancyGuard.dbg.json +++ b/backend/artifacts/@openzeppelin/contracts/utils/ReentrancyGuard.sol/ReentrancyGuard.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/169ec88754f8ab831077ca9fbb049cf4.json" + "buildInfo": "../../../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/contracts/DLE.sol/DLE.dbg.json b/backend/artifacts/contracts/DLE.sol/DLE.dbg.json index 9b902d5..8ca2940 100644 --- a/backend/artifacts/contracts/DLE.sol/DLE.dbg.json +++ b/backend/artifacts/contracts/DLE.sol/DLE.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../build-info/998bc5520c3173891dd242df2365077b.json" + "buildInfo": "../../build-info/3e12480a731f7a845287f0f150241bb4.json" } diff --git a/backend/artifacts/contracts/DLE.sol/DLE.json b/backend/artifacts/contracts/DLE.sol/DLE.json index 19b9866..6f54454 100644 --- a/backend/artifacts/contracts/DLE.sol/DLE.json +++ b/backend/artifacts/contracts/DLE.sol/DLE.json @@ -765,25 +765,6 @@ "name": "ProposalTargetsSet", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "timelock", - "type": "uint256" - } - ], - "name": "ProposalTimelockSet", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -1200,7 +1181,7 @@ }, { "internalType": "uint256", - "name": "_timelockDelay", + "name": "", "type": "uint256" } ], @@ -1714,11 +1695,6 @@ "name": "governanceChainId", "type": "uint256" }, - { - "internalType": "uint256", - "name": "timelock", - "type": "uint256" - }, { "internalType": "uint256", "name": "snapshotTimepoint", @@ -2161,11 +2137,6 @@ "name": "governanceChainId", "type": "uint256" }, - { - "internalType": "uint256", - "name": "timelock", - "type": "uint256" - }, { "internalType": "uint256", "name": "snapshotTimepoint", @@ -2337,8 +2308,8 @@ "type": "function" } ], - "bytecode": "0x6101608060405234620001f857620080518038038091620000208262000213565b833980820160408212620001f85782516001600160401b0392838211620001f85781906101809182910312620001f8576200005a6200027f565b9082860151858111620001f85784876200007792860101620002f7565b825280830151858111620001f85784876200009592860101620002f7565b60208301526101a0830151858111620001f8578487620000b892860101620002f7565b60408301526101c0830151858111620001f8578487620000db92860101620002f7565b60608301526101e0830151608083015261020083015160a0830152610220830151858111620001f857848762000114928601016200036a565b60c083015261024083015160e0830152610260830151956101009687840152610280840151868111620001f85785826200015192870101620003f5565b9561012096878501526102a0850151818111620001f857868362000178928801016200046c565b9561014096878601526102c0860151918211620001f85782620001a292620001ae9701016200046c565b90830152519062001209565b60405191615f6f938462002082853960805184612ee0015260a05184612f9b015260c05184612eaa015260e05184612f2f01525183612f55015251826118bc015251816118e80152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b601f01601f1916610160908101906001600160401b038211908210176200023957604052565b620001fd565b604081019081106001600160401b038211176200023957604052565b601f909101601f19168101906001600160401b038211908210176200023957604052565b6040519061018082016001600160401b038111838210176200023957604052565b6040519061014082016001600160401b038111838210176200023957604052565b60405190620002d0826200023f565b565b60005b838110620002e65750506000910152565b8181015183820152602001620002d5565b81601f82011215620001f85780516001600160401b0381116200023957604051926200032e601f8301601f1916602001856200025b565b81845260208284010111620001f8576200034f9160208085019101620002d2565b90565b6001600160401b038111620002395760051b60200190565b9080601f83011215620001f857815190620003858262000352565b926200039560405194856200025b565b828452602092838086019160051b83010192808411620001f857848301915b848310620003c55750505050505090565b82516001600160401b038111620001f8578691620003e984848094890101620002f7565b815201920191620003b4565b81601f82011215620001f8578051916200040f8362000352565b926200041f60405194856200025b565b808452602092838086019260051b820101928311620001f8578301905b8282106200044b575050505090565b81516001600160a01b0381168103620001f85781529083019083016200043c565b81601f82011215620001f857805191620004868362000352565b926200049660405194856200025b565b808452602092838086019260051b820101928311620001f8578301905b828210620004c2575050505090565b81518152908301908301620004b3565b90600182811c9216801562000504575b6020831014620004ee57565b634e487b7160e01b600052602260045260246000fd5b91607f1691620004e2565b8181106200051b575050565b600081556001016200050f565b90601f821162000536575050565b620002d09160036000526020600020906020601f840160051c8301931062000567575b601f0160051c01906200050f565b909150819062000559565b90601f821162000580575050565b620002d09160046000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f8211620005be575050565b620002d09160056000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f8211620005fc575050565b620002d09160066000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f82116200063a575050565b620002d091600d6000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f821162000678575050565b620002d091600e6000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f8211620006b6575050565b620002d091600f6000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f8211620006f4575050565b620002d091600c6000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b9190601f81116200073457505050565b620002d0926000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b80519091906001600160401b03811162000239576200078e8162000788600454620004d2565b62000572565b602080601f8311600114620007cd5750819293600092620007c1575b50508160011b916000199060031b1c191617600455565b015190503880620007aa565b6004600052601f198316949091907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b926000905b8782106200083c57505083600195961062000822575b505050811b01600455565b015160001960f88460031b161c1916905538808062000817565b8060018596829496860151815501950193019062000801565b80519091906001600160401b038111620002395762000881816200087b600d54620004d2565b6200062c565b602080601f8311600114620008c05750819293600092620008b4575b50508160011b916000199060031b1c191617600d55565b0151905038806200089d565b600d600052601f198316949091907fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5926000905b8782106200092f57505083600195961062000915575b505050811b01600d55565b015160001960f88460031b161c191690553880806200090a565b80600185968294968601518155019501930190620008f4565b80519091906001600160401b038111620002395762000974816200096e600e54620004d2565b6200066a565b602080601f8311600114620009b35750819293600092620009a7575b50508160011b916000199060031b1c191617600e55565b01519050388062000990565b600e600052601f198316949091907fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd926000905b87821062000a2257505083600195961062000a08575b505050811b01600e55565b015160001960f88460031b161c19169055388080620009fd565b80600185968294968601518155019501930190620009e7565b80519091906001600160401b038111620002395762000a678162000a61600f54620004d2565b620006a8565b602080601f831160011462000aa6575081929360009262000a9a575b50508160011b916000199060031b1c191617600f55565b01519050388062000a83565b600f600052601f198316949091907f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802926000905b87821062000b1557505083600195961062000afb575b505050811b01600f55565b015160001960f88460031b161c1916905538808062000af0565b8060018596829496860151815501950193019062000ada565b81519192916001600160401b038111620002395762000b5a8162000b538454620004d2565b8462000724565b602080601f831160011462000b9957508192939460009262000b8d575b50508160011b916000199060031b1c1916179055565b01519050388062000b77565b90601f1983169562000bb085600052602060002090565b926000905b88821062000bf05750508360019596971062000bd6575b505050811b019055565b015160001960f88460031b161c1916905538808062000bcc565b8060018596829496860151815501950193019062000bb5565b634e487b7160e01b600052601160045260246000fd5b80519068010000000000000000821162000239576012548260125580831062000c91575b50601260005260209081019060008051602062007ff18339815191526000925b84841062000c72575050505050565b6001838262000c848394518662000b2e565b0192019301929062000c63565b6012600090815260008051602062007ff18339815191529182019184015b82811062000cbf57505062000c43565b8062000cce60019254620004d2565b8062000cdd575b500162000caf565b601f90818111841462000cf75750508281555b3862000cd5565b8362000d1c9262000d0d85600052602060002090565b920160051c820191016200050f565b6000818152602081208183555562000cf0565b805180516001600160401b038111620002395762000d5a8162000d54600c54620004d2565b620006e6565b6020918290601f831160011462000e1b5762000dfd938361012094620002d0979462000da89460009262000e0f575b50508160011b916000199060031b1c191617600c555b82015162000855565b62000db7604082015162000948565b62000dc6606082015162000a3b565b608081015160105560a081015160115562000de560c082015162000c1f565b60e08101516013556101008101516014550151151590565b60ff8019601554169115151617601555565b01519050388062000d89565b600c600052601f19831691907fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c79260005b81811062000e9e575084620002d0979462000da89462000dfd9894610120986001951062000e84575b505050811b01600c5562000d9f565b015160001960f88460031b161c1916905538808062000e75565b92938660018192878601518155019501930162000e4c565b600019811462000ec65760010190565b62000c09565b634e487b7160e01b600052603260045260246000fd5b805182101562000ef75760209160051b010190565b62000ecc565b601e546801000000000000000081101562000239576001810180601e5581101562000ef757601e6000527f50bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e3500155565b1562000f5457565b60405162461bcd60e51b815260206004820152601660248201527f417272617973206c656e677468206d69736d61746368000000000000000000006044820152606490fd5b1562000fa157565b60405162461bcd60e51b815260206004820152601360248201527f4e6f20696e697469616c20706172746e657273000000000000000000000000006044820152606490fd5b1562000fee57565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606490fd5b156200102a57565b60405162461bcd60e51b815260206004820152600b60248201526a16995c9bc8185b5bdd5b9d60aa1b6044820152606490fd5b90815180825260208080930193019160005b8281106200107e575050505090565b8351855293810193928101926001016200106f565b9092916040820191604081528451809352606081019260208096019060005b818110620010cf575050506200034f93948184039101526200105d565b82516001600160a01b031686529487019491870191600101620010b2565b906020916200110881518092818552858086019101620002d2565b601f01601f1916010190565b96989a999795926200115d906200114e6200113e6200116c959794610140808d528c0190620010ed565b6020978b8203898d0152620010ed565b9089820360408b0152620010ed565b908782036060890152620010ed565b92608086015260a085015283820360c08501528551908183528083019281808460051b8301019801936000915b848310620011d8575050505050506200034f9495620011c99160e084015261010083019060018060a01b03169052565b6101208184039101526200105d565b9091929394988480620011f8600193601f198682030187528d51620010ed565b9b0193019301919493929062001199565b80519260208201938451816200121f926200146f565b81519284519260408101928351936060830190815194608085019889519660a087019788519060c08901519260e08a019b8c51956200125d620002a0565b9e8f91825260208201526040015260608d015260808c015260a08b015260c08a015260e089015261010042818a0152610120988981016200129e9060019052565b620012a99062000d2f565b85015160165560185560005b61016085018051805183101562001321576200130e83809362001307620012fa620012e96200131b98620013159762000ee2565b51600052601d602052604060002090565b805460ff19166001179055565b5162000ee2565b5162000efd565b62000eb6565b620012b5565b505050929597909396919497860195865151986200134861014083019a8b51511462000f4c565b62001357885151151562000f99565b60005b88518051821015620013d65790620013158c620013c96200139e84620013966200138982620013d09962000ee2565b516001600160a01b031690565b935162000ee2565b51620013b56001600160a01b038416151562000fe6565b620013c281151562001022565b82620015e2565b8062001f92565b6200135a565b5050909192939598977ff9e7aa11bcdcbb8ac33b5dba92fca799ef091e54c29270822065501d8edea1a57f11b248463a1620b36a975da8f250009f56fb5dd0e9d5027a90a834d0ee84d6f6996200146a9799519051906200143d6040519283928362001093565b0390a18251935196519751945190519061016060c0850151935194015195604051998a9930978b62001114565b0390a1565b929190926040519062001482826200023f565b60019283835260209081840194603160f81b865287519060018060401b0382116200023957620014bf82620014b9600354620004d2565b62000528565b8398601f831160011462001555578291620014fc95969798999a839260009462001549575b50501b916000199060031b1c19161760035562000762565b6200150782620016b0565b610120526200151683620017c0565b61014052815191012060e052519020610100524660a0526200153762001925565b6080523060c052620002d06001600b55565b015192503880620014e4565b6003600052601f198316999192917fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9160005b8c8110620015cc575083620014fc9798999a9b9c10620015b2575b505050811b0160035562000762565b015160001960f88460031b161c19169055388080620015a3565b8183015184559285019291870191870162001588565b91906001600160a01b0383168015620016975760025482810180911162000ec6576002556001600160a01b038416600090815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a3600254926001600160d01b0384116200166d57620002d092935062001991565b604051630e58ae9360e11b8152600481018590526001600160d01b036024820152604490fd5b0390fd5b60405163ec442f0560e01b815260006004820152602490fd5b9081516020808210600014620016ce575050906200034f90620018d0565b6001600160401b0382116200023957620016f582620016ef600554620004d2565b620005b0565b80601f831160011462001735575081929360009262001729575b50508160011b916000199060031b1c19161760055560ff90565b0151905038806200170f565b6005600052601f198316949091907f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0926000905b878210620017a75750508360019596106200178d575b505050811b0160055560ff90565b015160001960f88460031b161c191690553880806200177f565b8060018596829496860151815501950193019062001769565b9081516020808210600014620017de575050906200034f90620018d0565b6001600160401b03821162000239576200180582620017ff600654620004d2565b620005ee565b80601f831160011462001845575081929360009262001839575b50508160011b916000199060031b1c19161760065560ff90565b0151905038806200181f565b6006600052601f198316949091907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f926000905b878210620018b75750508360019596106200189d575b505050811b0160065560ff90565b015160001960f88460031b161c191690553880806200188f565b8060018596829496860151815501950193019062001879565b601f815111620018fe576020815191015160208210620018ee571790565b6000198260200360031b1b161790565b60405163305a27a960e01b81526020600482015290819062001693906024830190620010ed565b60e051610100516040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815260c0810181811060018060401b03821117620002395760405251902090565b906200199d8162001ccd565b9165ffffffffffff80431162001a7b57600a5460008162001a48575050620019d990620019d0620002d09560006200204d565b90431662001dc9565b50506001600160a01b0390811690811562001a2b575b60086020527f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c75460009283526040909220548116911662001a9a565b62001a4062001a3a8462001ccd565b62001c18565b5050620019ef565b60009291921995838781011162000ec657620002d096620019d994602084600a620019d096522001015460301c6200204d565b6040516306dfcc6560e41b815260306004820152436024820152604490fd5b6001600160a01b0380831693929190811690818514158062001c0e575b62001ac4575b5050505050565b8162001b40575b50508262001adc575b808062001abd565b6001600160a01b03166000908152600960205260409020600080516020620080318339815191529162001b1c9162001b15909162001ccd565b9062001c75565b604080516001600160d01b039384168152919092166020820152a238808062001ad4565b6001600160a01b0316600090815260096020526040902062001b628462001ccd565b9065ffffffffffff9081431162001a7b57805460008162001bcf5750509062001bac9162001ba26000805160206200803183398151915294600062002067565b9143169062001ec5565b604080516001600160d01b039384168152919092166020820152a2388062001acb565b6000939291931994848681011162000ec657600080516020620080318339815191529562001bac956020848662001ba296522001015460301c62002067565b5083151562001ab7565b65ffffffffffff80431162001a7b57600a5460008162001c49575050620019d062001c4592600062002067565b9091565b9092600019848181011162000ec65762001c4594602084600a620019d096522001015460301c62002067565b65ffffffffffff9081431162001a7b57805460008162001ca257505062001ba262001c459360006200204d565b9093600019858181011162000ec65762001c45956020848662001ba296522001015460301c6200204d565b6001600160d01b039081811162001ce2571690565b604490604051906306dfcc6560e41b825260d060048301526024820152fd5b60001981019190821162000ec657565b600a54906801000000000000000082101562000239576001820180600a5582101562000ef757600a60005280516020919091015160301b65ffffffffffff191665ffffffffffff91909116176000805160206200801183398151915290910155565b9081546801000000000000000081101562000239576001810180845581101562000ef75760009283526020928390208251929093015160301b65ffffffffffff191665ffffffffffff9290921691909117910155565b600a54919291801562001e965762001de562001dfe9162001d01565b600a600052600080516020620080118339815191520190565b9081549165ffffffffffff9081841691831680831162001e845786920362001e465762001e3f92509065ffffffffffff82549181199060301b169116179055565b60301c9190565b505062001e7e9062001e6962001e5b620002c1565b65ffffffffffff9092168252565b6001600160d01b038516602082015262001d11565b62001e3f565b604051632520601d60e01b8152600490fd5b5062001ebf9062001eaa62001e5b620002c1565b6001600160d01b038416602082015262001d11565b60009190565b8054929392801562001f685762001ee062001eed9162001d01565b8260005260206000200190565b9182549265ffffffffffff9182851692811680841162001e845787930362001f2f575062001e3f92509065ffffffffffff82549181199060301b169116179055565b91505062001e7e9162001f5362001f45620002c1565b65ffffffffffff9093168352565b6001600160d01b038616602083015262001d73565b509062001ebf9162001f7d62001f45620002c1565b6001600160d01b038516602083015262001d73565b6001600160a01b039081169180821691828403620020085760008481526008602052604080822080546001600160a01b031981168717909155620002d096931694909285907f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f8480a48060205220549162001a9a565b60405162461bcd60e51b815260206004820152601360248201527f44656c65676174696f6e2064697361626c6564000000000000000000000000006044820152606490fd5b6001600160d01b039182169082160190811162000ec65790565b6001600160d01b039182169082160390811162000ec6579056fe6080604052600436101561001257600080fd5b60003560e01c8063013cf08b146103de57806306fdde03146103d9578063078f6208146103d4578063095ea7b3146103cf5780630c0512e9146103ca5780630d61b519146103c557806318160ddd146103c0578063204c5d1f146103bb57806322dbefbb1461030c57806322f3e2d4146103b657806323b872dd146103b15780632519ae5c146103ac578063313ce567146103a75780633644e515146103a25780633a46b1a8146102d557806347c661401461039d5780634b145793146103075780634bf5d7e9146103985780634cf2ab32146103935780634cfd16bb1461038e5780634de184f6146103845780634fa76ec9146103895780635221c1f014610384578063548d496f1461037f578063587cde1e1461037a5780635c19a95c146103755780635cf0e8a4146103705780636cbadbfa146103705780636dcf811d1461036b5780636fcfff451461036657806370a08231146103615780637ce288ea1461035c5780637e5a9b47146103575780637ecebe00146103525780637f6dda141461034d57806384b0196e1461034857806385e59ce2146103435780638e539e8c1461033e5780639080936f1461033957806391ddadf41461033457806395d89b411461032f57806398e527d31461032a5780639a49bdde146103255780639ab24eb014610320578063a351f6151461031b578063a9059cbb14610316578063adf7420714610311578063b0b6cc1a1461030c578063b3fe8bcb14610307578063c3cda52014610302578063c8a6d06e146102fd578063c97bfe6b146102f8578063c9a3c0c7146102f3578063c9d27afe146102ee578063d505accf146102e9578063dcf628c0146102e4578063dd62ed3e146102df578063e49a62e9146102da578063eaeded5f146102d5578063eced3dfb146102d0578063f1127ed8146102cb5763f2c26a47146102c657600080fd5b6128bb565b612795565b612777565b6112d6565b612759565b6126f6565b612659565b6124a8565b61235b565b612226565b6121d5565b612139565b611ff7565b611397565b610f45565b611ce7565b611c8d565b611b4f565b611b06565b611ae8565b611aca565b611a23565b6119f7565b6119ce565b61199c565b611965565b6118a3565b61186d565b611830565b611802565b611777565b61173a565b6116cd565b6116aa565b61168c565b611664565b611625565b6115f4565b61159f565b6115d6565b611525565b6114b2565b6113c8565b611301565b6112b3565b611297565b6110ec565b610fb0565b610f79565b610e62565b610d32565b610c26565b610c08565b610bd3565b610b93565b610ab2565b6109f5565b90600182811c92168015610413575b60208310146103fd57565b634e487b7160e01b600052602260045260246000fd5b91607f16916103f2565b600d546000929161042d826103e3565b80825291600190818116908115610492575060011461044b57505050565b91929350600d600052600080516020615eda833981519152916000925b84841061047a57505060209250010190565b80546020858501810191909152909301928101610468565b915050602093945060ff929192191683830152151560051b010190565b600e54600092916104bf826103e3565b8082529160019081811690811561049257506001146104dd57505050565b91929350600e600052600080516020615e9a833981519152916000925b84841061050c57505060209250010190565b805460208585018101919091529093019281016104fa565b600f5460009291610534826103e3565b80825291600190818116908115610492575060011461055257505050565b91929350600f600052600080516020615f1a833981519152916000925b84841061058157505060209250010190565b8054602085850181019190915290930192810161056f565b90600092918054916105aa836103e3565b91828252600193848116908160001461060c57506001146105cc575b50505050565b90919394506000526020928360002092846000945b8386106105f85750505050010190388080806105c6565b8054858701830152940193859082016105e1565b9294505050602093945060ff191683830152151560051b010190388080806105c6565b634e487b7160e01b600052604160045260246000fd5b61014081019081106001600160401b0382111761066157604052565b61062f565b604081019081106001600160401b0382111761066157604052565b60a081019081106001600160401b0382111761066157604052565b60c081019081106001600160401b0382111761066157604052565b90601f801991011681019081106001600160401b0382111761066157604052565b60405190600082600c54916106ec836103e3565b808352926001908181169081156107625750600114610715575b50610713925003836106b7565b565b600c60009081529150600080516020615e7a8339815191525b8483106107475750610713935050810160200138610706565b81935090816020925483858a0101520191019091859261072e565b90506020925061071394915060ff191682840152151560051b82010138610706565b60405190600082600d5491610798836103e3565b8083529260019081811690811561076257506001146107be5750610713925003836106b7565b600d60009081529150600080516020615eda8339815191525b8483106107f05750610713935050810160200138610706565b81935090816020925483858a010152019101909185926107d7565b60405190600082600e549161081f836103e3565b8083529260019081811690811561076257506001146108455750610713925003836106b7565b600e60009081529150600080516020615e9a8339815191525b8483106108775750610713935050810160200138610706565b81935090816020925483858a0101520191019091859261085e565b60405190600082600f54916108a6836103e3565b8083529260019081811690811561076257506001146108cc5750610713925003836106b7565b600f60009081529150600080516020615f1a8339815191525b8483106108fe5750610713935050810160200138610706565b81935090816020925483858a010152019101909185926108e5565b9061071361092d9260405193848092610599565b03836106b7565b60005b8381106109475750506000910152565b8181015183820152602001610937565b9060209161097081518092818552858086019101610934565b601f01601f1916010190565b989490936109a86109e4989497936101609c9f9e9d9a968c5260208c61018091829101528c0190610957565b60408b019790975260608a015215156080890152151560a088015260c08701526001600160a01b031660e0860152848203610100860152610957565b956101208301526101408201520152565b34610a99576020366003190112610a9957600435600052601b60205260406000208054610a9560405191610a3783610a308160018801610599565b03846106b7565b600284015460038501546004860154600587015460068801549397929492936001600160a01b031690610a6c60078601610919565b92600886015494600b600a880154970154976040519b8c9b60ff808660081c169516938d61097c565b0390f35b600080fd5b906020610aaf928181520190610957565b90565b34610a9957600080600319360112610b90576040519080600354610ad5816103e3565b80855291600191808316908115610b665750600114610b0b575b610a9585610aff818703826106b7565b60405191829182610a9e565b9250600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b828410610b4e575050508101602001610aff82610a95610aef565b80546020858701810191909152909301928101610b33565b869550610a9596935060209250610aff94915060ff191682840152151560051b8201019293610aef565b80fd5b34610a99576000366003190112610a99576060601654601854601e549060405192835260208301526040820152f35b6001600160a01b03811603610a9957565b34610a99576040366003190112610a9957610bfd600435610bf381610bc2565b6024359033612bf5565b602060405160018152f35b34610a99576000366003190112610a99576020601754604051908152f35b34610a99576020366003190112610a99577fbadbd87941bb6424ed4aa4719bf01a3319b64480e49f89018c718603239553d26004356007610c7182600052601b602052604060002090565b610c7d8382541461402d565b610cfc60048201610c9e610c99610c95835460ff1690565b1590565b6140b4565b610caf60185460088501541461423b565b610cdf610cbb866141cd565b60058601544210801590610d2b575b610cd390614286565b81610d23575b506142e2565b610cef600a840154421015614324565b805460ff19166001179055565b0190610d0f610d0a83610919565b614aa7565b610d1e60405192839283614367565b0390a1005b905038610cd9565b5080610cca565b34610a99576000366003190112610a99576020600254604051908152f35b90815180825260208092019182818360051b85019501936000915b848310610d7b5750505050505090565b9091929394958480610d9583856001950387528a51610957565b9801930193019194939290610d6b565b610aaf90602081528251610e3d610dca61014092836020860152610160850190610957565b610e14610e00610dec602089015193601f1994858983030160408a0152610957565b604089015184888303016060890152610957565b606088015183878303016080880152610957565b90608087015160a086015260a087015160c086015260c0870151908583030160e0860152610d50565b9360e08101516101009081850152810151906101209182850152015191019015159052565b34610a9957600080600319360112610b9057610a9590610f39604051610e8781610645565b60609283825283602083015283604083015283808301528060808301528060a08301528360c08301528060e083015261010090808284015261012080930152610ece611065565b93610ed76106d8565b8552610ee1610784565b6020860152610eee61080b565b6040860152610efb610892565b90850152601054608085015260115460a0850152610f17615621565b60c085015260135460e08501526014549084015260155460ff16151590830152565b60405191829182610da5565b34610a99576020366003190112610a99576004356000526019602052602060018060a01b0360406000205416604051908152f35b34610a99576000366003190112610a995760ff601f54161580610fa4575b6020906040519015158152f35b5060155460ff16610f97565b34610a99576060366003190112610a9957600435610fcd81610bc2565b602435610fd981610bc2565b6001600160a01b03821660009081526001602090815260408083203384529091529020604435919054926000198410611023575b6110179350612ae3565b60405160018152602090f35b82841061103f5761103a8361101795033383612ca9565b61100d565b604051637dc7a0d960e11b81523360048201526024810185905260448101849052606490fd5b6040519061071382610645565b6040519061071382610666565b6001600160401b03811161066157601f01601f191660200190565b9291926110a68261107f565b916110b460405193846106b7565b829481845281830111610a99578281602093846000960137010152565b9080601f83011215610a9957816020610aaf9335910161109a565b34610a995760a0366003190112610a99576004356001600160401b038111610a995761111f610a959136906004016110d1565b7f7585f467599d0f008985f231af99293be388626ac16ca59505c2f8f88969cd636112846044359261127660643561115681610bc2565b61117e611179611172608435600052601d602052604060002090565b5460ff1690565b613629565b6111926001600160a01b038216151561543e565b6111b46111af610c9561117289600052601a602052604060002090565b615479565b3360009081526020819052604090206111d0905b541515613585565b6007601754966111e76111e2896136aa565b601755565b6112706111fe89600052601b602052604060002090565b9189835561120f8760018501613b81565b61121b60243542613250565b60058401556006830180546001600160a01b031916331790556040516304fa45bf60e31b602082015260248101919091526001600160a01b03909416604485015283606481015b03601f1981018552846106b7565b01613b81565b604051918291338684613d69565b0390a16040519081529081906020820190565b34610a99576000366003190112610a9957602060405160128152f35b34610a99576000366003190112610a995760206112ce612ea7565b604051908152f35b34610a99576040366003190112610a995760206112ce6004356112f881610bc2565b602435906129d2565b34610a99576020366003190112610a995760043580600052601b60205261132f60406000209182541461402d565b606461135a60018060d01b0361135061134b600b860154612a8c565b61325d565b16601654906141ba565b049060036002820154910154918282019081831161139257604080519384526020840194909452928201526060810191909152608090f35b612acd565b34610a99576020366003190112610a9957600435600052601a602052602060ff604060002054166040519015158152f35b34610a99576000366003190112610a99576113e2436131f4565b65ffffffffffff806113f3436131f4565b1691160361144857610a9560405161140a81610666565b601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c740000006020820152604051918291602083526020830190610957565b6040516301bfc1c560e61b8152600490fd5b634e487b7160e01b600052603260045260246000fd5b601e5481101561149557601e600052600080516020615efa8339815191520190600090565b61145a565b80548210156114955760005260206000200190600090565b34610a99576020366003190112610a9957600435601e54811015610a9957602090601e600052600080516020615efa8339815191520154604051908152f35b90815180825260208080930193019160005b828110611511575050505090565b835185529381019392810192600101611503565b34610a99576000366003190112610a995760405180601e54808252826020809301601e600052600080516020615efa8339815191529260005b8582821061158957505050611575925003836106b7565b610a956040519282849384528301906114f1565b855484526001958601958895509301920161155e565b34610a99576020366003190112610a995760206115cc600435600052601d60205260ff6040600020541690565b6040519015158152f35b34610a99576000366003190112610a99576020601654604051908152f35b34610a99576020366003190112610a9957600435600052601d602052602060ff604060002054166040519015158152f35b34610a99576020366003190112610a9957602060043561164481610bc2565b60018060a01b038091166000526008825260406000205416604051908152f35b34610a99576020366003190112610a995761168a60043561168481610bc2565b33615da9565b005b34610a99576000366003190112610a99576020601854604051908152f35b34610a99576000366003190112610a9957602060ff601f54166040519015158152f35b34610a99576020366003190112610a99576004356116ea81610bc2565b6001600160a01b031660009081526009602052604090205463ffffffff9081811161171b5760209160405191168152f35b604490604051906306dfcc6560e41b8252602060048301526024820152fd5b34610a99576020366003190112610a995760206112ce60043561175c81610bc2565b6001600160a01b031660009081526020819052604090205490565b34610a99576020366003190112610a9957600435611794816147f4565b156117c65760207f57df5a6a467271f04b10f7fe9e66d21dcd8ae7eaf079099d48959f24a53b691091604051908152a1005b60405162461bcd60e51b81526020600482015260146024820152734e6f7420616c6c20636861696e7320726561647960601b6044820152606490fd5b34610a99576020366003190112610a995760406118206004356141cd565b8251911515825215156020820152f35b34610a99576020366003190112610a995760043561184d81610bc2565b60018060a01b031660005260076020526020604060002054604051908152f35b34610a99576040366003190112610a9957610a9561188f6024356004356156f3565b6040519182916020835260208301906114f1565b34610a99576000366003190112610a99576119366118e07f0000000000000000000000000000000000000000000000000000000000000000613041565b610a9561190c7f000000000000000000000000000000000000000000000000000000000000000061313a565b611944611917612fe7565b91604051958695600f60f81b875260e0602088015260e0870190610957565b908582036040870152610957565b90466060850152306080850152600060a085015283820360c08501526114f1565b34610a99576020366003190112610a9957602060646119936001600160d01b0361135061134b600435612a8c565b04604051908152f35b34610a99576020366003190112610a995760206001600160d01b036119c561134b600435612a8c565b16604051908152f35b34610a99576020366003190112610a995760206119ec60043561579e565b60ff60405191168152f35b34610a99576000366003190112610a99576020611a13436131f4565b65ffffffffffff60405191168152f35b34610a9957600080600319360112610b90576040519080600454611a46816103e3565b80855291600191808316908115610b665750600114611a6f57610a9585610aff818703826106b7565b9250600483527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b828410611ab2575050508101602001610aff82610a95610aef565b80546020858701810191909152909301928101611a97565b34610a99576000366003190112610a99576020601c54604051908152f35b34610a99576020366003190112610a995760206112ce60043561485b565b34610a99576020366003190112610a9957600435611b2381610bc2565b6001600160a01b031660009081526009602090815260409091206001600160d01b03906119c5906134f6565b34610a99576040366003190112610a99576004356001600160401b03602435818111610a995736602382011215610a99578060040135918211610a99573660248383010111610a9957610d1e60249284611c7f611bd77fc7c129e53e59dadfa16305619e80c7519f1f6912c10915359fd75b56bcecdd7b97600052601b602052604060002090565b611be38382541461402d565b611c70600b6004830192611c03611bfe60ff86541615151590565b614409565b611c1260058201544210614079565b6006810154611c3c90611c35906001600160a01b03165b6001600160a01b031690565b3314614448565b0154611c69611c4b82336129d2565b916001600160d01b0390611c629061134b90612a8c565b16916141a4565b1015614485565b805461ff001916610100179055565b6040519485940190846144dd565b34610a99576040366003190112610a9957610bfd600435611cad81610bc2565b6024359033612ae3565b9181601f84011215610a99578235916001600160401b038311610a99576020808501948460051b010111610a9957565b34610a99576060366003190112610a99576001600160401b03600435602435828111610a9957611d1b903690600401611cb7565b92604435908111610a995783611d3684923690600401611cb7565b611d3e614181565b611d5284600052601b602052604060002090565b90611d5f8583541461402d565b6004820192611d7a611d75610c95865460ff1690565b61450b565b60185494611d8e6008850154871415614567565b611da0611d9b8786615876565b6145c3565b611db0600a850154421015614324565b611dbb838214614606565b611e45876007860197611e3d600b611dd28b610919565b6020815191012098015497611e2f896040519485936020850197889094939260809260a08301967f45de75acfcd4cbcc5691559486749bf0d5eb65e4b24c59ac2f258ba6bfceaa3484526020840152604083015260608201520152565b03601f1981018352826106b7565b519020612fc1565b9760009889945b838610611f0d575050507fda7dba8f94d70cde423cce3a243bebf95d2ec927507b566f67e329dcfe2d06bb877fbadbd87941bb6424ed4aa4719bf01a3319b64480e49f89018c718603239553d2611ee689611ecd8a610cef8f611ec6611ebf8e61135061134b60018060d01b0392612a8c565b6064900490565b1115614765565b611ed9610d0a82610919565b6040519182918583614367565b0390a1601854604080519283526020830191909152819081015b0390a161168a6001600b55565b909192939499868b611f49611c29611f44611f3c611f36611f2f868a8f614643565b369161109a565b896147b1565b938a8a614684565b614694565b6001600160a01b03821690611f5f90821461469e565b8d88886000925b8310611fa2575050505091611f81611f9292611f98946129d2565b90611f8d821515614719565b613250565b9a6136aa565b9493929190611e4c565b8394955092611fbe611c29611f4485611fc595611fca98614684565b14156146da565b6136aa565b90899291888f8990611f66565b6064359060ff82168203610a9957565b6084359060ff82168203610a9957565b34610a995760c0366003190112610a995760043561201481610bc2565b60443590602435612023611fd7565b8342116120ab5761209f61168a946120a6926040519060208201927fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf845260018060a01b038816604084015286606084015260808301526080825261208782610681565b61209a60a4359360843593519020612fc1565b612d52565b9182612cfc565b615da9565b604051632341d78760e11b815260048101859052602490fd5b6001600160401b0381116106615760051b60200190565b81601f82011215610a99578035916120f2836120c4565b9261210060405194856106b7565b808452602092838086019260051b820101928311610a99578301905b82821061212a575050505090565b8135815290830190830161211c565b34610a995760c0366003190112610a99576001600160401b03600435818111610a995761216a9036906004016110d1565b90604435818111610a995736602382011215610a995761219490369060248160040135910161109a565b608435918211610a9957610a95926121b36121c59336906004016120db565b9060a435926064359160243590613da8565b6040519081529081906020820190565b34610a99576020366003190112610a9957600435601c54811015610a9957602090601c6000527f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a2110154604051908152f35b34610a99576080366003190112610a99576004356001600160401b038111610a9957612259610a959136906004016110d1565b7f7585f467599d0f008985f231af99293be388626ac16ca59505c2f8f88969cd636112846044359261229d611179611172606435600052601d602052604060002090565b6122bc6122b761117286600052601a602052604060002090565b6154bd565b3360009081526020819052604090206122d4906111c8565b6112766112626007601754966122ec6111e2896136aa565b61127061230389600052601b602052604060002090565b918983556123148760018501613b81565b61232060243542613250565b60058401556006830180546001600160a01b03191633179055604051633972e9fb60e21b602082015260248101919091529384906044820190565b34610a99576040366003190112610a99576004356024358015158103610a99577f78975aaf742630489badd22949b88ac50eaaea576339ee05440b671a33bfb6a9916123a5614181565b611f006123bc82600052601b602052604060002090565b6123c88382541461402d565b6123d760058201544210614079565b6123eb610c99610c95600484015460ff1690565b600c81019061241a612415610c9561117233869060018060a01b0316600052602052604060002090565b614100565b61242b60185460088301541461413c565b612453610cef61243f600b840154336129d2565b336000908152602095909552604090942090565b841561249357600201612467828254613250565b90555b604080519384523360208501529315159383019390935260608201929092529081906080820190565b6003016124a1828254613250565b905561246a565b34610a995760e0366003190112610a99576004356124c581610bc2565b6024356124d181610bc2565b604435906064356124e0611fe7565b8142116125cb576001600160a01b0385811660008181526007602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99281019283529283019390935292861660608201526080810187905260a081019190915260c08082019490945292835261258492909161257160e0836106b7565b61209a60c4359360a43593519020612fc1565b6001600160a01b03848116908216036125a1575061168a92612bf5565b6040516325c0072360e11b81526001600160a01b0391821660048201529084166024820152604490fd5b60405163313c898160e11b815260048101839052602490fd5b9895929a97949161260a90610aaf9d9b9895928b526101808060208d01528b0190610957565b60408a019b909b52606089015215156080880152151560a087015260c08601526001600160a01b031660e0850152610100840152610120830152610140820152808303610160909101526114f1565b34610a99576020366003190112610a995760043580600052601b6020526040600020612688815492831461402d565b610a95600282015492600383015490600484015460058501546126b4600687015460018060a01b031690565b600887015491600a88015493600b890154956126de60096126d760018d01610919565b9b016156a4565b976040519b8c9b60ff808660081c169516938d6125e4565b34610a99576040366003190112610a9957602061275060043561271881610bc2565b6024359061272582610bc2565b60018060a01b03166000526001835260406000209060018060a01b0316600052602052604060002090565b54604051908152f35b34610a99576020366003190112610a995760206115cc6004356147f4565b34610a99576000366003190112610a99576020601e54604051908152f35b34610a99576040366003190112610a99576004356127b281610bc2565b6024359063ffffffff82168203610a9957610a9591612802916127d3612ce3565b506127dc612ce3565b506001600160a01b031660009081526009602052604090206127fc612ce3565b5061149a565b506040519061281082610666565b5465ffffffffffff811680835260309190911c60209283019081526040805192835290516001600160d01b031692820192909252918291820190565b9794999895926128919061288361289f946128756101009b98958d610120908181520190610957565b8c810360208e015290610957565b908a820360408c0152610957565b9088820360608a0152610957565b97608087015260a086015260c085015260e08401521515910152565b34610a9957600080600319360112610b9057604051908181600c546128df816103e3565b808452936001918083169081156129ae5750600114612963575b5050612907925003826106b7565b604051906129188261092d8161041d565b610a956040516129328161292b816104af565b03826106b7565b6040516129428161292b81610524565b601054601154601354916014549360ff6015541695604051998a998a61284c565b9150600c8252600080516020615e7a8339815191525b8483106129935750612907935050810160200138806128f9565b81935090816020925483858901015201910190918492612979565b9150506020925061290794915060ff191682840152151560051b82010138806128f9565b6001600160a01b0316600090815260096020526040812090916129f490612a8c565b81549083829160058411612a3d575b612a0e935084613524565b80612a225750505b6001600160d01b031690565b91612a2f60209293613226565b92815220015460301c612a16565b9192612a4881613381565b810390811161139257612a0e9385875265ffffffffffff808360208a2001541690851610600014612a7a575091612a03565b929150612a8690613242565b90612a03565b65ffffffffffff612a9c436131f4565b1680821015612aaf5750610aaf906131f4565b6044925060405191637669fc0f60e11b835260048301526024820152fd5b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0380821694939291908515612bdc5782168015612bc3576001600160a01b03821660009081526020819052604090205495848710612b945784610713969703612b458460018060a01b03166000526000602052604060002090565b556001600160a01b0384166000908152602081815260409182902080548801905590518681527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a36158c1565b60405163391434e360e21b81526001600160a01b03841660048201526024810188905260448101869052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b6001600160a01b038082169291908315612c90578216938415612c775780612c6d7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92594612c5660209560018060a01b03166000526001602052604060002090565b9060018060a01b0316600052602052604060002090565b55604051908152a3565b604051634a1406b160e11b815260006004820152602490fd5b60405163e602df0560e01b815260006004820152602490fd5b906001600160a01b0380831615612c9057811615612c7757612c56612ce09260018060a01b03166000526001602052604060002090565b55565b60405190612cf082610666565b60006020838281520152565b6001600160a01b03811660009081526007602052604090208054600181019091559091819003612d2a575050565b6040516301d4b62360e61b81526001600160a01b039092166004830152602482015260449150fd5b91610aaf9391612d6193612d6a565b90929192612e1a565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612dee57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612de25780516001600160a01b03811615612dd957918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b60041115612e0457565b634e487b7160e01b600052602160045260246000fd5b612e2381612dfa565b80612e2c575050565b612e3581612dfa565b60018103612e4f5760405163f645eedf60e01b8152600490fd5b612e5881612dfa565b60028103612e795760405163fce698f760e01b815260048101839052602490fd5b80612e85600392612dfa565b14612e8d5750565b6040516335e2f38360e21b81526004810191909152602490fd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480612f98575b15612f02577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a08152612f928161069c565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614612ed9565b604290612fcc612ea7565b906040519161190160f01b8352600283015260228201522090565b604051602081018181106001600160401b038211176106615760405260008152906000368137565b90613019826120c4565b61302660405191826106b7565b8281528092613037601f19916120c4565b0190602036910137565b60ff811461307f5760ff811690601f821161306d576040519161306383610666565b8252602082015290565b604051632cd44ac360e21b8152600490fd5b50604051600554816000613092836103e3565b8083529260019081811690811561311857506001146130b9575b50610aaf925003826106b7565b6005600090815291507f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8483106130fd5750610aaf9350508101602001386130ac565b819350908160209254838589010152019101909184926130e4565b905060209250610aaf94915060ff191682840152151560051b820101386130ac565b60ff811461315c5760ff811690601f821161306d576040519161306383610666565b5060405160065481600061316f836103e3565b8083529260019081811690811561311857506001146131955750610aaf925003826106b7565b6006600090815291507ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8483106131d95750610aaf9350508101602001386130ac565b819350908160209254838589010152019101909184926131c0565b65ffffffffffff90818111613207571690565b604490604051906306dfcc6560e41b8252603060048301526024820152fd5b60001981019190821161139257565b9190820391821161139257565b906001820180921161139257565b9190820180921161139257565b600a80546000816005811161330b575b509290925b8381106132b1575050600091801560001461328f57505050600090565b61329890613226565b9152600080516020615eba833981519152015460301c90565b90928082169080831860011c8201809211611392578360005265ffffffffffff8083600080516020615eba833981519152015416908616106000146132f95750925b90613272565b93915061330590613242565b906132f3565b909161331682613381565b82039182116113925783835265ffffffffffff8083600080516020615eba833981519152015416908616106000146133515750905b3861326d565b915061335c90613242565b61334b565b811561336b570490565b634e487b7160e01b600052601260045260246000fd5b6001811115610aaf57600181600160801b81101561349a575b61344261343861342e61342461341a61341061344e97600488600160401b6134499a101561348d575b640100000000811015613480575b62010000811015613473575b610100811015613467575b601081101561345b575b1015613453575b60030260011c613409818b613361565b0160011c90565b613409818a613361565b6134098189613361565b6134098188613361565b6134098187613361565b6134098186613361565b8093613361565b821190565b900390565b60011b6133f9565b811c9160021b916133f2565b60081c91811b916133e8565b60101c9160081b916133dd565b60201c9160101b916133d1565b60401c9160201b916133c3565b50600160401b9050608082901c61339a565b600a54600090806134be575050600090565b8060001981011161139257600a7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a79252015460301c90565b80546000918161350857505050600090565b6000199282848101116113925760209181522001015460301c90565b91905b8382106135345750505090565b9091928083169080841860011c82018092116113925760008581526020902082015465ffffffffffff90811690841610156135735750925b9190613527565b93925061357f90613242565b9161356c565b1561358c57565b60405162461bcd60e51b815260206004820152602360248201527f4d75737420686f6c6420746f6b656e7320746f206372656174652070726f706f6044820152621cd85b60ea1b6064820152608490fd5b156135e457565b60405162461bcd60e51b815260206004820152601960248201527f4475726174696f6e206d75737420626520706f736974697665000000000000006044820152606490fd5b1561363057565b60405162461bcd60e51b815260206004820152601360248201527210da185a5b881b9bdd081cdd5c1c1bdc9d1959606a1b6044820152606490fd5b1561367257565b60405162461bcd60e51b815260206004820152601060248201526f54696d656c6f636b20746f6f2062696760801b6044820152606490fd5b60001981146113925760010190565b8181106136c4575050565b600081556001016136b9565b90601f82116136dd575050565b61071391600c600052600080516020615e7a833981519152906020601f840160051c83019310613715575b601f0160051c01906136b9565b9091508190613708565b90601f821161372c575050565b61071391600d600052600080516020615eda833981519152906020601f840160051c8301931061371557601f0160051c01906136b9565b90601f8211613770575050565b61071391600e600052600080516020615e9a833981519152906020601f840160051c8301931061371557601f0160051c01906136b9565b90601f82116137b4575050565b61071391600f600052600080516020615f1a833981519152906020601f840160051c8301931061371557601f0160051c01906136b9565b9190601f81116137fa57505050565b610713926000526020600020906020601f840160051c8301931061371557601f0160051c01906136b9565b9081516001600160401b0381116106615761384a81613845600c546103e3565b6136d0565b602080601f8311600114613886575081929360009261387b575b50508160011b916000199060031b1c191617600c55565b015190503880613864565b90601f198316946138a7600c600052600080516020615e7a83398151915290565b926000905b8782106138e45750508360019596106138cb575b505050811b01600c55565b015160001960f88460031b161c191690553880806138c0565b806001859682949686015181550195019301906138ac565b9081516001600160401b038111610661576139218161391c600d546103e3565b61371f565b602080601f831160011461395d5750819293600092613952575b50508160011b916000199060031b1c191617600d55565b01519050388061393b565b90601f1983169461397e600d600052600080516020615eda83398151915290565b926000905b8782106139bb5750508360019596106139a2575b505050811b01600d55565b015160001960f88460031b161c19169055388080613997565b80600185968294968601518155019501930190613983565b9081516001600160401b038111610661576139f8816139f3600e546103e3565b613763565b602080601f8311600114613a345750819293600092613a29575b50508160011b916000199060031b1c191617600e55565b015190503880613a12565b90601f19831694613a55600e600052600080516020615e9a83398151915290565b926000905b878210613a92575050836001959610613a79575b505050811b01600e55565b015160001960f88460031b161c19169055388080613a6e565b80600185968294968601518155019501930190613a5a565b9081516001600160401b03811161066157613acf81613aca600f546103e3565b6137a7565b602080601f8311600114613b0b5750819293600092613b00575b50508160011b916000199060031b1c191617600f55565b015190503880613ae9565b90601f19831694613b2c600f600052600080516020615f1a83398151915290565b926000905b878210613b69575050836001959610613b50575b505050811b01600f55565b015160001960f88460031b161c19169055388080613b45565b80600185968294968601518155019501930190613b31565b91909182516001600160401b03811161066157613ba881613ba284546103e3565b846137eb565b602080601f8311600114613be4575081929394600092613bd9575b50508160011b916000199060031b1c1916179055565b015190503880613bc3565b90601f19831695613bfa85600052602060002090565b926000905b888210613c3757505083600195969710613c1e575b505050811b019055565b015160001960f88460031b161c19169055388080613c14565b80600185968294968601518155019501930190613bff565b80518210156114955760209160051b010190565b15613c6a57565b60405162461bcd60e51b815260206004820152601a60248201527f54617267657420636861696e206e6f7420737570706f727465640000000000006044820152606490fd5b601c54600160401b811015610661576001810180601c5581101561149557601c6000527f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a2110155565b601e54600160401b811015610661576001810180601e5581101561149557601e600052600080516020615efa8339815191520155565b90815491600160401b8310156106615782613d509160016107139501815561149a565b90919082549060031b91821b91600019901b1916179055565b9081526001600160a01b039091166020820152606060408201819052610aaf92910190610957565b604090610aaf9392815281602082015201906114f1565b33600090815260208190526040902092949392909190613dc7906111c8565b613dd28115156135dd565b613dec61117961117285600052601d602052604060002090565b613dfc6301e1338087111561366b565b613e8f60175496613e0f6111e2896136aa565b613e83613e2689600052601b602052604060002090565b97898955613e61600195613e3c88888d01613b81565b600060028c0155600060038c0155613e5b60048c0160ff198154169055565b42613250565b60058a01556006890180546001600160a01b0319163317905560078901613b81565b84600888015542613250565b94600a8101958655613eae613ea3436131f4565b65ffffffffffff1690565b8061401c5750819060005b600b820155600960009101925b613fc7575b505050613fa5613fc1937fdb17271edb72bcaba16ce918d885db2e701491c9ff3f713f80caf9d614aa9ff4613f957ff46a1614ca62096cf230d10ea203eb985f7a60d98cdffc807d794181bc0a9f9a97957f7585f467599d0f008985f231af99293be388626ac16ca59505c2f8f88969cd637f5d1231ca3a274bcd2f510e0d53a889213ebf0315b86ee6bb9d73da08fba7460696613f688c613caf565b8b613f7a604051928392339084613d69565b0390a1604080518b8152602081019290925290918291820190565b0390a16040519182918883613d91565b0390a15460408051858152602081019290925290918291820190565b0390a190565b85518110156140175780613ffd613ff8611172613fe7614011958b613c4f565b51600052601d602052604060002090565b613c63565b611fc561400a8289613c4f565b5185613d2d565b81613ec6565b613ecb565b61402590613226565b908291613eb9565b1561403457565b60405162461bcd60e51b815260206004820152601760248201527f50726f706f73616c20646f6573206e6f742065786973740000000000000000006044820152606490fd5b1561408057565b60405162461bcd60e51b815260206004820152600c60248201526b159bdd1a5b99c8195b99195960a21b6044820152606490fd5b156140bb57565b60405162461bcd60e51b815260206004820152601960248201527f50726f706f73616c20616c7265616479206578656375746564000000000000006044820152606490fd5b1561410757565b60405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e481d9bdd1959609a1b6044820152606490fd5b1561414357565b60405162461bcd60e51b815260206004820152601660248201527557726f6e6720636861696e20666f7220766f74696e6760501b6044820152606490fd5b6002600b5414614192576002600b55565b604051633ee5aeb560e01b8152600490fd5b90600a820291808304600a149015171561139257565b8181029291811591840414171561139257565b9081600052601b6020526141e860406000209283541461402d565b60028201546003830154928382019081831161139257600b015460649061421f906001600160d01b03906113509061134b90612a8c565b04111592839182614231575b50509190565b119050388061422b565b1561424257565b606460405162461bcd60e51b815260206004820152602060248201527f45786563757465206f6e6c7920696e20676f7665726e616e636520636861696e6044820152fd5b1561428d57565b60405162461bcd60e51b815260206004820152602760248201527f566f74696e67206e6f7420656e64656420616e642071756f72756d206e6f74206044820152661c995858da195960ca1b6064820152608490fd5b156142e957565b60405162461bcd60e51b8152602060048201526013602482015272141c9bdc1bdcd85b081b9bdd081c185cdcd959606a1b6044820152606490fd5b1561432b57565b60405162461bcd60e51b8152602060048201526014602482015273151a5b595b1bd8dac81b9bdd08195e1c1a5c995960621b6044820152606490fd5b919082526020916040838201526000928254614382816103e3565b9384604085015260019182811690816000146143e457506001146143a9575b505050505090565b6000908152828120949550935b8585106143d05750505060609250010138808080806143a1565b8054858501606001529382019381016143b6565b93505050506060935060ff929192191683830152151560051b010138808080806143a1565b1561441057565b60405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e48195e1958dd5d195960821b6044820152606490fd5b1561444f57565b60405162461bcd60e51b815260206004820152600e60248201526d27b7363c9034b734ba34b0ba37b960911b6044820152606490fd5b1561448c57565b60405162461bcd60e51b815260206004820152602360248201527f496e73756666696369656e7420766f74696e6720706f77657220746f2063616e60448201526218d95b60ea1b6064820152608490fd5b91926060938192845260406020850152816040850152848401376000828201840152601f01601f1916010190565b1561451257565b60405162461bcd60e51b815260206004820152602760248201527f50726f706f73616c20616c726561647920657865637574656420696e20746869604482015266399031b430b4b760c91b6064820152608490fd5b1561456e57565b60405162461bcd60e51b815260206004820152602760248201527f557365206578656375746550726f706f73616c20696e20676f7665726e616e63604482015266329031b430b4b760c91b6064820152608490fd5b156145ca57565b60405162461bcd60e51b8152602060048201526014602482015273436861696e206e6f7420696e207461726765747360601b6044820152606490fd5b1561460d57565b60405162461bcd60e51b815260206004820152600e60248201526d426164207369676e61747572657360901b6044820152606490fd5b91908110156114955760051b81013590601e1981360301821215610a995701908135916001600160401b038311610a99576020018236038113610a99579190565b91908110156114955760051b0190565b35610aaf81610bc2565b156146a557565b60405162461bcd60e51b815260206004820152600d60248201526c426164207369676e617475726560981b6044820152606490fd5b156146e157565b60405162461bcd60e51b815260206004820152601060248201526f223ab83634b1b0ba329039b4b3b732b960811b6044820152606490fd5b1561472057565b60405162461bcd60e51b815260206004820152601b60248201527f4e6f20766f74696e6720706f77657220617420736e617073686f7400000000006044820152606490fd5b1561476c57565b60405162461bcd60e51b815260206004820152601a60248201527f51756f72756d206e6f74207265616368656420627920736967730000000000006044820152606490fd5b8151610aaf92612d619260401983016147e9576147e292506020820151906060604084015193015160001a90612d6a565b9192909190565b505060009160029190565b61480d600091808352601b60205260408320541461402d565b80601e54915b82811061482257505050600190565b61484261482e8261485b565b600052601d60205260ff6040600020541690565b1561485557614850906136aa565b614813565b50905090565b601e5481101561487e57601e600052600080516020615efa833981519152015490565b60405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840c6d0c2d2dc40d2dcc8caf606b1b6044820152606490fd5b909291926148c68161107f565b916148d460405193846106b7565b829482845282820111610a99576020610713930190610934565b9190604083820312610a995782516001600160e01b031981168103610a9957926020810151906001600160401b038211610a9957019080601f83011215610a99578151610aaf926020016148b9565b90816020910312610a99575190565b9190826040910312610a995760208251920151610aaf81610bc2565b9080601f83011215610a99578151610aaf926020016148b9565b9080601f83011215610a995781519061499a826120c4565b926149a860405194856106b7565b828452602092838086019160051b83010192808411610a9957848301915b8483106149d65750505050505090565b82516001600160401b038111610a995786916149f784848094890101614968565b8152019201916149c6565b91909161010081840312610a99578051916001600160401b0392838111610a995784614a2f918401614968565b936020830151848111610a995781614a48918501614968565b936040840151818111610a995782614a61918601614968565b936060810151828111610a995783614a7a918301614968565b9360808201519360a08301519360c0840151908111610a995760e091614aa1918501614982565b92015190565b614abb6020918280825183010191016148ee565b91906001600160e01b031916630236fce560e51b8103614afa57508181614aeb9261071394518301019101614a02565b96959095949194939293615206565b63f0f9e6b760e01b8103614b2357508181614b1e926107139451830101910161493d565b615304565b632ab43f7f60e11b8103614b4c57508181614b47926107139451830101910161493d565b6153a4565b6304fa45bf60e31b8103614b7f57508181614b70926107139451830101910161494c565b6001600160a01b031690615501565b633972e9fb60e21b8103614ba857508181614ba3926107139451830101910161493d565b6155b1565b63093f734560e31b8103614bd157508181614bcc926107139451830101910161493d565b614c44565b633e78500160e21b8103614bfa57508181614bf5926107139451830101910161493d565b614ddf565b633cdb568760e11b14915061071390505760405162461bcd60e51b81526020600482015260116024820152702ab735b737bbb71037b832b930ba34b7b760791b6044820152606490fd5b80600052601d60205260ff60406000205416614cf2576018548114614cad57614ca881614c9f610cef7fbba9d55e9fd1a441b1617724e2fdb76777d15ec77ab2b72ac15952cbe97085db94600052601d602052604060002090565b6121c581613cf7565b0390a1565b60405162461bcd60e51b815260206004820152601860248201527f43616e6e6f74206164642063757272656e7420636861696e00000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601760248201527f436861696e20616c726561647920737570706f727465640000000000000000006044820152606490fd5b15614d3e57565b60405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f742072656d6f76652063757272656e7420636861696e00000000006044820152606490fd5b601e548015614dc95760001981019080821015611495577f50bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e34f600091601e83520155601e55565b634e487b7160e01b600052603160045260246000fd5b614dff60ff614df883600052601d602052604060002090565b5416613629565b614e0d601854821415614d37565b614e2e614e2482600052601d602052604060002090565b805460ff19169055565b60005b601e5480821015614eb55782614e53614e4984611470565b90549060031b1c90565b14614e675750614e62906136aa565b614e31565b91614ead614ca892613d50614ea7614e49614ea27f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d598613226565b611470565b91611470565b6121c5614d83565b5050614ca87f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d5916121c5565b15614ee857565b60405162461bcd60e51b815260206004820152601660248201527553796d626f6c2063616e6e6f7420626520656d70747960501b6044820152606490fd5b15614f2d57565b60405162461bcd60e51b815260206004820152601860248201527f4c6f636174696f6e2063616e6e6f7420626520656d70747900000000000000006044820152606490fd5b15614f7957565b60405162461bcd60e51b815260206004820152601460248201527324b73b30b634b210353ab934b9b234b1ba34b7b760611b6044820152606490fd5b15614fbc57565b60405162461bcd60e51b815260206004820152600d60248201526c496e76616c6964204f4b544d4f60981b6044820152606490fd5b15614ff857565b60405162461bcd60e51b815260206004820152600b60248201526a0496e76616c6964204b50560ac1b6044820152606490fd5b805190600160401b821161066157601254826012558083106150a3575b5060126000526020908101907fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34446000925b848410615087575050505050565b6001838261509783945186613b81565b01920193019290615079565b600060128152837fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344492830192015b8281106150df575050615048565b806150ec600192546103e3565b806150f9575b50016150d1565b601f9081811184146151115750508281555b386150f2565b836151339261512585600052602060002090565b920160051c820191016136b9565b6000818152602081208183555561510b565b9897969495926151889061517a61516a6151969597948d610100908181520190610957565b6020978d89818403910152610957565b908b820360408d0152610957565b9089820360608b0152610957565b93608088015260a087015285830360c08701528151908184528084019381808460051b8301019401946000915b8483106151d857505050505060e09150930152565b909192939484806151f5600193601f198682030187528a51610957565b9801930193019195949392906151c3565b94909591939692968551156152c8577f62d6efdb8dbca656ac38d327c1d66a4ccaeabc91c464fe5e7352b604858f5f4697614ca89561524789511515614ee1565b61525381511515614f26565b61525e831515614f72565b615269841515614fb5565b615274861515614ff1565b61527d88613825565b615286896138fc565b61528f816139d3565b61529882613aaa565b6152a183601055565b6152aa84601155565b6152b38561502b565b6152bc86601355565b60405198899889615145565b60405162461bcd60e51b81526020600482015260146024820152734e616d652063616e6e6f7420626520656d70747960601b6044820152606490fd5b80151580615399575b156153545760168054908290556040805191825260208201929092527fd0198ea88bf9c4ad5317b68e697944e524541fcb494d854f095b1cd88a097ab69181908101614ca8565b60405162461bcd60e51b815260206004820152601960248201527f496e76616c69642071756f72756d2070657263656e74616765000000000000006044820152606490fd5b50606481111561530d565b80600052601d6020526153be60ff60406000205416613629565b601854908181146154095760188190556040805192835260208301919091527f979103c7afbf0138fe781172504ceb318ff78f9a420de8cabac8141f0121b521919081908101614ca8565b60405162461bcd60e51b815260206004820152600d60248201526c14d85b594818da185a5b881251609a1b6044820152606490fd5b1561544557565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606490fd5b1561548057565b60405162461bcd60e51b81526020600482015260156024820152744d6f64756c6520616c72656164792065786973747360581b6044820152606490fd5b156154c457565b60405162461bcd60e51b8152602060048201526015602482015274135bd91d5b1948191bd95cc81b9bdd08195e1a5cdd605a1b6044820152606490fd5b7ff14475b19484bf096265507cc0c41cd3bf1994992088806830686e2d7272271991906155386001600160a01b038316151561543e565b80600052601a60205261555360ff6040600020541615615479565b600081815260196020526040902080546001600160a01b0319166001600160a01b038416179055601a602090815260406000819020805460ff1916600117905580519283526001600160a01b03909316908201529081908101614ca8565b60207f4c7c76abe482a2c36ea52f1b999474c69f8b4afeeac5635f8aea2526864ba8539180600052601a82526155ee60ff604060002054166154bd565b600081815260198352604080822080546001600160a01b0319169055601a845290819020805460ff1916905551908152a1565b6012549061562e826120c4565b91604061563d815194856106b7565b8184528360208091019160126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444906000935b85851061568157505050505050565b600184819284516156968161292b818a610599565b815201930194019391615672565b9060405191828154918282526020928383019160005283600020936000905b8282106156d957505050610713925003836106b7565b8554845260019586019588955093810193909101906156c3565b601c9081549283821015615792578101918282116113925783831161578a575b818303838111611392576157269061300f565b93825b84811061573857505050505090565b81811015611495576157859083600052807f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a211015461577f6157798784613235565b89613c4f565b526136aa565b615729565b839250615713565b50505050610aaf612fe7565b6157b281600052601b602052604060002090565b906157bf8183541461402d565b600482015460ff8160081c1661586e5760ff16615867576157df906141cd565b60058301544210828115948161585f575b81615850575b506158475782918261582e575b5050615827578161581e575b5061581957600090565b600290565b9050153861580f565b5050600190565b8492509061583f575b503880615803565b905038615837565b50505050600590565b600a91500154421015386157f6565b8391506157f0565b5050600390565b505050600490565b9060005b6009830180548210156158b85761589282849261149a565b90549060031b1c146158b0576158a96009916136aa565b905061587a565b505050600190565b50505050600090565b6001600160a01b0390811692918190841561594d575b16908115615905575b6107139360005260086020528060406000205416916000526040600020541690615992565b61590e83615b1a565b93615918436131f4565b6001600160d01b0395868061592b6134ac565b1691169003958611611392576107139561594491615c04565b505093506158e0565b905061595883615b1a565b90615962436131f4565b6001600160d01b039283806159756134ac565b1691160192831161139257839261598b91615c04565b50506158d7565b6001600160a01b03808316939291908116908185141580615adb575b6159ba575b5050505050565b81615a3f575b5050826159cf575b80806159b3565b6001600160a01b031660009081526009602052604090207fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72491615a1c91615a169091615b1a565b90615ae4565b604080516001600160d01b039384168152919092166020820152a23880806159c8565b6001600160a01b03166000908152600960205260409020615a5f84615b1a565b615a68436131f4565b6001600160d01b03918280615a7c866134f6565b169116900392828411611392577fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72493615ad192615ab892615ced565b6040805192851683529316602082015291829190820190565b0390a238806159c0565b508315156159ae565b90615aee436131f4565b6001600160d01b03918280615b02866134f6565b1691160191821161139257615b1692615ced565b9091565b6001600160d01b0390818111615b2e571690565b604490604051906306dfcc6560e41b825260d060048301526024820152fd5b600a5490600160401b821015610661576001820180600a5582101561149557600a600052805160209091015160301b65ffffffffffff191665ffffffffffff9190911617600080516020615eba83398151915290910155565b8054600160401b81101561066157615bc39160018201815561149a565b615bee57815160209092015160301b65ffffffffffff191665ffffffffffff92909216919091179055565b634e487b7160e01b600052600060045260246000fd5b600a549192918015615cc357615c1c615c3491613226565b600a600052600080516020615eba8339815191520190565b9081549165ffffffffffff90818416918316808311615cb157869203615c7957615c7292509065ffffffffffff82549181199060301b169116179055565b60301c9190565b5050615cac90615c98615c8a611072565b65ffffffffffff9092168252565b6001600160d01b0385166020820152615b4d565b615c72565b604051632520601d60e01b8152600490fd5b50615ce790615cd3615c8a611072565b6001600160d01b0384166020820152615b4d565b60009190565b80549293928015615d8457615d04615d1191613226565b8260005260206000200190565b9182549265ffffffffffff91828516928116808411615cb157879303615d505750615c7292509065ffffffffffff82549181199060301b169116179055565b915050615cac91615d70615d62611072565b65ffffffffffff9093168352565b6001600160d01b0386166020830152615ba6565b5090615ce791615d95615d62611072565b6001600160d01b0385166020830152615ba6565b6001600160a01b03808316929181811690848203615e3e57600082815260086020526040902080546001600160a01b031981166001600160a01b038716179091556107139593169392615e389285907f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f600080a46001600160a01b031660009081526020819052604090205490565b91615992565b60405162461bcd60e51b815260206004820152601360248201527211195b1959d85d1a5bdb88191a5cd8589b1959606a1b6044820152606490fdfedf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7bb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fdc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8d7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb550bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e3508d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802a2646970667358221220342bb23de0ffd74d2c73ab1bca80be5afb39937e0bdb34deb68fe801c38061eb64736f6c63430008140033bb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444c65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724", - "deployedBytecode": "0x6080604052600436101561001257600080fd5b60003560e01c8063013cf08b146103de57806306fdde03146103d9578063078f6208146103d4578063095ea7b3146103cf5780630c0512e9146103ca5780630d61b519146103c557806318160ddd146103c0578063204c5d1f146103bb57806322dbefbb1461030c57806322f3e2d4146103b657806323b872dd146103b15780632519ae5c146103ac578063313ce567146103a75780633644e515146103a25780633a46b1a8146102d557806347c661401461039d5780634b145793146103075780634bf5d7e9146103985780634cf2ab32146103935780634cfd16bb1461038e5780634de184f6146103845780634fa76ec9146103895780635221c1f014610384578063548d496f1461037f578063587cde1e1461037a5780635c19a95c146103755780635cf0e8a4146103705780636cbadbfa146103705780636dcf811d1461036b5780636fcfff451461036657806370a08231146103615780637ce288ea1461035c5780637e5a9b47146103575780637ecebe00146103525780637f6dda141461034d57806384b0196e1461034857806385e59ce2146103435780638e539e8c1461033e5780639080936f1461033957806391ddadf41461033457806395d89b411461032f57806398e527d31461032a5780639a49bdde146103255780639ab24eb014610320578063a351f6151461031b578063a9059cbb14610316578063adf7420714610311578063b0b6cc1a1461030c578063b3fe8bcb14610307578063c3cda52014610302578063c8a6d06e146102fd578063c97bfe6b146102f8578063c9a3c0c7146102f3578063c9d27afe146102ee578063d505accf146102e9578063dcf628c0146102e4578063dd62ed3e146102df578063e49a62e9146102da578063eaeded5f146102d5578063eced3dfb146102d0578063f1127ed8146102cb5763f2c26a47146102c657600080fd5b6128bb565b612795565b612777565b6112d6565b612759565b6126f6565b612659565b6124a8565b61235b565b612226565b6121d5565b612139565b611ff7565b611397565b610f45565b611ce7565b611c8d565b611b4f565b611b06565b611ae8565b611aca565b611a23565b6119f7565b6119ce565b61199c565b611965565b6118a3565b61186d565b611830565b611802565b611777565b61173a565b6116cd565b6116aa565b61168c565b611664565b611625565b6115f4565b61159f565b6115d6565b611525565b6114b2565b6113c8565b611301565b6112b3565b611297565b6110ec565b610fb0565b610f79565b610e62565b610d32565b610c26565b610c08565b610bd3565b610b93565b610ab2565b6109f5565b90600182811c92168015610413575b60208310146103fd57565b634e487b7160e01b600052602260045260246000fd5b91607f16916103f2565b600d546000929161042d826103e3565b80825291600190818116908115610492575060011461044b57505050565b91929350600d600052600080516020615eda833981519152916000925b84841061047a57505060209250010190565b80546020858501810191909152909301928101610468565b915050602093945060ff929192191683830152151560051b010190565b600e54600092916104bf826103e3565b8082529160019081811690811561049257506001146104dd57505050565b91929350600e600052600080516020615e9a833981519152916000925b84841061050c57505060209250010190565b805460208585018101919091529093019281016104fa565b600f5460009291610534826103e3565b80825291600190818116908115610492575060011461055257505050565b91929350600f600052600080516020615f1a833981519152916000925b84841061058157505060209250010190565b8054602085850181019190915290930192810161056f565b90600092918054916105aa836103e3565b91828252600193848116908160001461060c57506001146105cc575b50505050565b90919394506000526020928360002092846000945b8386106105f85750505050010190388080806105c6565b8054858701830152940193859082016105e1565b9294505050602093945060ff191683830152151560051b010190388080806105c6565b634e487b7160e01b600052604160045260246000fd5b61014081019081106001600160401b0382111761066157604052565b61062f565b604081019081106001600160401b0382111761066157604052565b60a081019081106001600160401b0382111761066157604052565b60c081019081106001600160401b0382111761066157604052565b90601f801991011681019081106001600160401b0382111761066157604052565b60405190600082600c54916106ec836103e3565b808352926001908181169081156107625750600114610715575b50610713925003836106b7565b565b600c60009081529150600080516020615e7a8339815191525b8483106107475750610713935050810160200138610706565b81935090816020925483858a0101520191019091859261072e565b90506020925061071394915060ff191682840152151560051b82010138610706565b60405190600082600d5491610798836103e3565b8083529260019081811690811561076257506001146107be5750610713925003836106b7565b600d60009081529150600080516020615eda8339815191525b8483106107f05750610713935050810160200138610706565b81935090816020925483858a010152019101909185926107d7565b60405190600082600e549161081f836103e3565b8083529260019081811690811561076257506001146108455750610713925003836106b7565b600e60009081529150600080516020615e9a8339815191525b8483106108775750610713935050810160200138610706565b81935090816020925483858a0101520191019091859261085e565b60405190600082600f54916108a6836103e3565b8083529260019081811690811561076257506001146108cc5750610713925003836106b7565b600f60009081529150600080516020615f1a8339815191525b8483106108fe5750610713935050810160200138610706565b81935090816020925483858a010152019101909185926108e5565b9061071361092d9260405193848092610599565b03836106b7565b60005b8381106109475750506000910152565b8181015183820152602001610937565b9060209161097081518092818552858086019101610934565b601f01601f1916010190565b989490936109a86109e4989497936101609c9f9e9d9a968c5260208c61018091829101528c0190610957565b60408b019790975260608a015215156080890152151560a088015260c08701526001600160a01b031660e0860152848203610100860152610957565b956101208301526101408201520152565b34610a99576020366003190112610a9957600435600052601b60205260406000208054610a9560405191610a3783610a308160018801610599565b03846106b7565b600284015460038501546004860154600587015460068801549397929492936001600160a01b031690610a6c60078601610919565b92600886015494600b600a880154970154976040519b8c9b60ff808660081c169516938d61097c565b0390f35b600080fd5b906020610aaf928181520190610957565b90565b34610a9957600080600319360112610b90576040519080600354610ad5816103e3565b80855291600191808316908115610b665750600114610b0b575b610a9585610aff818703826106b7565b60405191829182610a9e565b9250600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b828410610b4e575050508101602001610aff82610a95610aef565b80546020858701810191909152909301928101610b33565b869550610a9596935060209250610aff94915060ff191682840152151560051b8201019293610aef565b80fd5b34610a99576000366003190112610a99576060601654601854601e549060405192835260208301526040820152f35b6001600160a01b03811603610a9957565b34610a99576040366003190112610a9957610bfd600435610bf381610bc2565b6024359033612bf5565b602060405160018152f35b34610a99576000366003190112610a99576020601754604051908152f35b34610a99576020366003190112610a99577fbadbd87941bb6424ed4aa4719bf01a3319b64480e49f89018c718603239553d26004356007610c7182600052601b602052604060002090565b610c7d8382541461402d565b610cfc60048201610c9e610c99610c95835460ff1690565b1590565b6140b4565b610caf60185460088501541461423b565b610cdf610cbb866141cd565b60058601544210801590610d2b575b610cd390614286565b81610d23575b506142e2565b610cef600a840154421015614324565b805460ff19166001179055565b0190610d0f610d0a83610919565b614aa7565b610d1e60405192839283614367565b0390a1005b905038610cd9565b5080610cca565b34610a99576000366003190112610a99576020600254604051908152f35b90815180825260208092019182818360051b85019501936000915b848310610d7b5750505050505090565b9091929394958480610d9583856001950387528a51610957565b9801930193019194939290610d6b565b610aaf90602081528251610e3d610dca61014092836020860152610160850190610957565b610e14610e00610dec602089015193601f1994858983030160408a0152610957565b604089015184888303016060890152610957565b606088015183878303016080880152610957565b90608087015160a086015260a087015160c086015260c0870151908583030160e0860152610d50565b9360e08101516101009081850152810151906101209182850152015191019015159052565b34610a9957600080600319360112610b9057610a9590610f39604051610e8781610645565b60609283825283602083015283604083015283808301528060808301528060a08301528360c08301528060e083015261010090808284015261012080930152610ece611065565b93610ed76106d8565b8552610ee1610784565b6020860152610eee61080b565b6040860152610efb610892565b90850152601054608085015260115460a0850152610f17615621565b60c085015260135460e08501526014549084015260155460ff16151590830152565b60405191829182610da5565b34610a99576020366003190112610a99576004356000526019602052602060018060a01b0360406000205416604051908152f35b34610a99576000366003190112610a995760ff601f54161580610fa4575b6020906040519015158152f35b5060155460ff16610f97565b34610a99576060366003190112610a9957600435610fcd81610bc2565b602435610fd981610bc2565b6001600160a01b03821660009081526001602090815260408083203384529091529020604435919054926000198410611023575b6110179350612ae3565b60405160018152602090f35b82841061103f5761103a8361101795033383612ca9565b61100d565b604051637dc7a0d960e11b81523360048201526024810185905260448101849052606490fd5b6040519061071382610645565b6040519061071382610666565b6001600160401b03811161066157601f01601f191660200190565b9291926110a68261107f565b916110b460405193846106b7565b829481845281830111610a99578281602093846000960137010152565b9080601f83011215610a9957816020610aaf9335910161109a565b34610a995760a0366003190112610a99576004356001600160401b038111610a995761111f610a959136906004016110d1565b7f7585f467599d0f008985f231af99293be388626ac16ca59505c2f8f88969cd636112846044359261127660643561115681610bc2565b61117e611179611172608435600052601d602052604060002090565b5460ff1690565b613629565b6111926001600160a01b038216151561543e565b6111b46111af610c9561117289600052601a602052604060002090565b615479565b3360009081526020819052604090206111d0905b541515613585565b6007601754966111e76111e2896136aa565b601755565b6112706111fe89600052601b602052604060002090565b9189835561120f8760018501613b81565b61121b60243542613250565b60058401556006830180546001600160a01b031916331790556040516304fa45bf60e31b602082015260248101919091526001600160a01b03909416604485015283606481015b03601f1981018552846106b7565b01613b81565b604051918291338684613d69565b0390a16040519081529081906020820190565b34610a99576000366003190112610a9957602060405160128152f35b34610a99576000366003190112610a995760206112ce612ea7565b604051908152f35b34610a99576040366003190112610a995760206112ce6004356112f881610bc2565b602435906129d2565b34610a99576020366003190112610a995760043580600052601b60205261132f60406000209182541461402d565b606461135a60018060d01b0361135061134b600b860154612a8c565b61325d565b16601654906141ba565b049060036002820154910154918282019081831161139257604080519384526020840194909452928201526060810191909152608090f35b612acd565b34610a99576020366003190112610a9957600435600052601a602052602060ff604060002054166040519015158152f35b34610a99576000366003190112610a99576113e2436131f4565b65ffffffffffff806113f3436131f4565b1691160361144857610a9560405161140a81610666565b601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c740000006020820152604051918291602083526020830190610957565b6040516301bfc1c560e61b8152600490fd5b634e487b7160e01b600052603260045260246000fd5b601e5481101561149557601e600052600080516020615efa8339815191520190600090565b61145a565b80548210156114955760005260206000200190600090565b34610a99576020366003190112610a9957600435601e54811015610a9957602090601e600052600080516020615efa8339815191520154604051908152f35b90815180825260208080930193019160005b828110611511575050505090565b835185529381019392810192600101611503565b34610a99576000366003190112610a995760405180601e54808252826020809301601e600052600080516020615efa8339815191529260005b8582821061158957505050611575925003836106b7565b610a956040519282849384528301906114f1565b855484526001958601958895509301920161155e565b34610a99576020366003190112610a995760206115cc600435600052601d60205260ff6040600020541690565b6040519015158152f35b34610a99576000366003190112610a99576020601654604051908152f35b34610a99576020366003190112610a9957600435600052601d602052602060ff604060002054166040519015158152f35b34610a99576020366003190112610a9957602060043561164481610bc2565b60018060a01b038091166000526008825260406000205416604051908152f35b34610a99576020366003190112610a995761168a60043561168481610bc2565b33615da9565b005b34610a99576000366003190112610a99576020601854604051908152f35b34610a99576000366003190112610a9957602060ff601f54166040519015158152f35b34610a99576020366003190112610a99576004356116ea81610bc2565b6001600160a01b031660009081526009602052604090205463ffffffff9081811161171b5760209160405191168152f35b604490604051906306dfcc6560e41b8252602060048301526024820152fd5b34610a99576020366003190112610a995760206112ce60043561175c81610bc2565b6001600160a01b031660009081526020819052604090205490565b34610a99576020366003190112610a9957600435611794816147f4565b156117c65760207f57df5a6a467271f04b10f7fe9e66d21dcd8ae7eaf079099d48959f24a53b691091604051908152a1005b60405162461bcd60e51b81526020600482015260146024820152734e6f7420616c6c20636861696e7320726561647960601b6044820152606490fd5b34610a99576020366003190112610a995760406118206004356141cd565b8251911515825215156020820152f35b34610a99576020366003190112610a995760043561184d81610bc2565b60018060a01b031660005260076020526020604060002054604051908152f35b34610a99576040366003190112610a9957610a9561188f6024356004356156f3565b6040519182916020835260208301906114f1565b34610a99576000366003190112610a99576119366118e07f0000000000000000000000000000000000000000000000000000000000000000613041565b610a9561190c7f000000000000000000000000000000000000000000000000000000000000000061313a565b611944611917612fe7565b91604051958695600f60f81b875260e0602088015260e0870190610957565b908582036040870152610957565b90466060850152306080850152600060a085015283820360c08501526114f1565b34610a99576020366003190112610a9957602060646119936001600160d01b0361135061134b600435612a8c565b04604051908152f35b34610a99576020366003190112610a995760206001600160d01b036119c561134b600435612a8c565b16604051908152f35b34610a99576020366003190112610a995760206119ec60043561579e565b60ff60405191168152f35b34610a99576000366003190112610a99576020611a13436131f4565b65ffffffffffff60405191168152f35b34610a9957600080600319360112610b90576040519080600454611a46816103e3565b80855291600191808316908115610b665750600114611a6f57610a9585610aff818703826106b7565b9250600483527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b828410611ab2575050508101602001610aff82610a95610aef565b80546020858701810191909152909301928101611a97565b34610a99576000366003190112610a99576020601c54604051908152f35b34610a99576020366003190112610a995760206112ce60043561485b565b34610a99576020366003190112610a9957600435611b2381610bc2565b6001600160a01b031660009081526009602090815260409091206001600160d01b03906119c5906134f6565b34610a99576040366003190112610a99576004356001600160401b03602435818111610a995736602382011215610a99578060040135918211610a99573660248383010111610a9957610d1e60249284611c7f611bd77fc7c129e53e59dadfa16305619e80c7519f1f6912c10915359fd75b56bcecdd7b97600052601b602052604060002090565b611be38382541461402d565b611c70600b6004830192611c03611bfe60ff86541615151590565b614409565b611c1260058201544210614079565b6006810154611c3c90611c35906001600160a01b03165b6001600160a01b031690565b3314614448565b0154611c69611c4b82336129d2565b916001600160d01b0390611c629061134b90612a8c565b16916141a4565b1015614485565b805461ff001916610100179055565b6040519485940190846144dd565b34610a99576040366003190112610a9957610bfd600435611cad81610bc2565b6024359033612ae3565b9181601f84011215610a99578235916001600160401b038311610a99576020808501948460051b010111610a9957565b34610a99576060366003190112610a99576001600160401b03600435602435828111610a9957611d1b903690600401611cb7565b92604435908111610a995783611d3684923690600401611cb7565b611d3e614181565b611d5284600052601b602052604060002090565b90611d5f8583541461402d565b6004820192611d7a611d75610c95865460ff1690565b61450b565b60185494611d8e6008850154871415614567565b611da0611d9b8786615876565b6145c3565b611db0600a850154421015614324565b611dbb838214614606565b611e45876007860197611e3d600b611dd28b610919565b6020815191012098015497611e2f896040519485936020850197889094939260809260a08301967f45de75acfcd4cbcc5691559486749bf0d5eb65e4b24c59ac2f258ba6bfceaa3484526020840152604083015260608201520152565b03601f1981018352826106b7565b519020612fc1565b9760009889945b838610611f0d575050507fda7dba8f94d70cde423cce3a243bebf95d2ec927507b566f67e329dcfe2d06bb877fbadbd87941bb6424ed4aa4719bf01a3319b64480e49f89018c718603239553d2611ee689611ecd8a610cef8f611ec6611ebf8e61135061134b60018060d01b0392612a8c565b6064900490565b1115614765565b611ed9610d0a82610919565b6040519182918583614367565b0390a1601854604080519283526020830191909152819081015b0390a161168a6001600b55565b909192939499868b611f49611c29611f44611f3c611f36611f2f868a8f614643565b369161109a565b896147b1565b938a8a614684565b614694565b6001600160a01b03821690611f5f90821461469e565b8d88886000925b8310611fa2575050505091611f81611f9292611f98946129d2565b90611f8d821515614719565b613250565b9a6136aa565b9493929190611e4c565b8394955092611fbe611c29611f4485611fc595611fca98614684565b14156146da565b6136aa565b90899291888f8990611f66565b6064359060ff82168203610a9957565b6084359060ff82168203610a9957565b34610a995760c0366003190112610a995760043561201481610bc2565b60443590602435612023611fd7565b8342116120ab5761209f61168a946120a6926040519060208201927fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf845260018060a01b038816604084015286606084015260808301526080825261208782610681565b61209a60a4359360843593519020612fc1565b612d52565b9182612cfc565b615da9565b604051632341d78760e11b815260048101859052602490fd5b6001600160401b0381116106615760051b60200190565b81601f82011215610a99578035916120f2836120c4565b9261210060405194856106b7565b808452602092838086019260051b820101928311610a99578301905b82821061212a575050505090565b8135815290830190830161211c565b34610a995760c0366003190112610a99576001600160401b03600435818111610a995761216a9036906004016110d1565b90604435818111610a995736602382011215610a995761219490369060248160040135910161109a565b608435918211610a9957610a95926121b36121c59336906004016120db565b9060a435926064359160243590613da8565b6040519081529081906020820190565b34610a99576020366003190112610a9957600435601c54811015610a9957602090601c6000527f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a2110154604051908152f35b34610a99576080366003190112610a99576004356001600160401b038111610a9957612259610a959136906004016110d1565b7f7585f467599d0f008985f231af99293be388626ac16ca59505c2f8f88969cd636112846044359261229d611179611172606435600052601d602052604060002090565b6122bc6122b761117286600052601a602052604060002090565b6154bd565b3360009081526020819052604090206122d4906111c8565b6112766112626007601754966122ec6111e2896136aa565b61127061230389600052601b602052604060002090565b918983556123148760018501613b81565b61232060243542613250565b60058401556006830180546001600160a01b03191633179055604051633972e9fb60e21b602082015260248101919091529384906044820190565b34610a99576040366003190112610a99576004356024358015158103610a99577f78975aaf742630489badd22949b88ac50eaaea576339ee05440b671a33bfb6a9916123a5614181565b611f006123bc82600052601b602052604060002090565b6123c88382541461402d565b6123d760058201544210614079565b6123eb610c99610c95600484015460ff1690565b600c81019061241a612415610c9561117233869060018060a01b0316600052602052604060002090565b614100565b61242b60185460088301541461413c565b612453610cef61243f600b840154336129d2565b336000908152602095909552604090942090565b841561249357600201612467828254613250565b90555b604080519384523360208501529315159383019390935260608201929092529081906080820190565b6003016124a1828254613250565b905561246a565b34610a995760e0366003190112610a99576004356124c581610bc2565b6024356124d181610bc2565b604435906064356124e0611fe7565b8142116125cb576001600160a01b0385811660008181526007602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99281019283529283019390935292861660608201526080810187905260a081019190915260c08082019490945292835261258492909161257160e0836106b7565b61209a60c4359360a43593519020612fc1565b6001600160a01b03848116908216036125a1575061168a92612bf5565b6040516325c0072360e11b81526001600160a01b0391821660048201529084166024820152604490fd5b60405163313c898160e11b815260048101839052602490fd5b9895929a97949161260a90610aaf9d9b9895928b526101808060208d01528b0190610957565b60408a019b909b52606089015215156080880152151560a087015260c08601526001600160a01b031660e0850152610100840152610120830152610140820152808303610160909101526114f1565b34610a99576020366003190112610a995760043580600052601b6020526040600020612688815492831461402d565b610a95600282015492600383015490600484015460058501546126b4600687015460018060a01b031690565b600887015491600a88015493600b890154956126de60096126d760018d01610919565b9b016156a4565b976040519b8c9b60ff808660081c169516938d6125e4565b34610a99576040366003190112610a9957602061275060043561271881610bc2565b6024359061272582610bc2565b60018060a01b03166000526001835260406000209060018060a01b0316600052602052604060002090565b54604051908152f35b34610a99576020366003190112610a995760206115cc6004356147f4565b34610a99576000366003190112610a99576020601e54604051908152f35b34610a99576040366003190112610a99576004356127b281610bc2565b6024359063ffffffff82168203610a9957610a9591612802916127d3612ce3565b506127dc612ce3565b506001600160a01b031660009081526009602052604090206127fc612ce3565b5061149a565b506040519061281082610666565b5465ffffffffffff811680835260309190911c60209283019081526040805192835290516001600160d01b031692820192909252918291820190565b9794999895926128919061288361289f946128756101009b98958d610120908181520190610957565b8c810360208e015290610957565b908a820360408c0152610957565b9088820360608a0152610957565b97608087015260a086015260c085015260e08401521515910152565b34610a9957600080600319360112610b9057604051908181600c546128df816103e3565b808452936001918083169081156129ae5750600114612963575b5050612907925003826106b7565b604051906129188261092d8161041d565b610a956040516129328161292b816104af565b03826106b7565b6040516129428161292b81610524565b601054601154601354916014549360ff6015541695604051998a998a61284c565b9150600c8252600080516020615e7a8339815191525b8483106129935750612907935050810160200138806128f9565b81935090816020925483858901015201910190918492612979565b9150506020925061290794915060ff191682840152151560051b82010138806128f9565b6001600160a01b0316600090815260096020526040812090916129f490612a8c565b81549083829160058411612a3d575b612a0e935084613524565b80612a225750505b6001600160d01b031690565b91612a2f60209293613226565b92815220015460301c612a16565b9192612a4881613381565b810390811161139257612a0e9385875265ffffffffffff808360208a2001541690851610600014612a7a575091612a03565b929150612a8690613242565b90612a03565b65ffffffffffff612a9c436131f4565b1680821015612aaf5750610aaf906131f4565b6044925060405191637669fc0f60e11b835260048301526024820152fd5b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0380821694939291908515612bdc5782168015612bc3576001600160a01b03821660009081526020819052604090205495848710612b945784610713969703612b458460018060a01b03166000526000602052604060002090565b556001600160a01b0384166000908152602081815260409182902080548801905590518681527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a36158c1565b60405163391434e360e21b81526001600160a01b03841660048201526024810188905260448101869052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b6001600160a01b038082169291908315612c90578216938415612c775780612c6d7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92594612c5660209560018060a01b03166000526001602052604060002090565b9060018060a01b0316600052602052604060002090565b55604051908152a3565b604051634a1406b160e11b815260006004820152602490fd5b60405163e602df0560e01b815260006004820152602490fd5b906001600160a01b0380831615612c9057811615612c7757612c56612ce09260018060a01b03166000526001602052604060002090565b55565b60405190612cf082610666565b60006020838281520152565b6001600160a01b03811660009081526007602052604090208054600181019091559091819003612d2a575050565b6040516301d4b62360e61b81526001600160a01b039092166004830152602482015260449150fd5b91610aaf9391612d6193612d6a565b90929192612e1a565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612dee57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612de25780516001600160a01b03811615612dd957918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b60041115612e0457565b634e487b7160e01b600052602160045260246000fd5b612e2381612dfa565b80612e2c575050565b612e3581612dfa565b60018103612e4f5760405163f645eedf60e01b8152600490fd5b612e5881612dfa565b60028103612e795760405163fce698f760e01b815260048101839052602490fd5b80612e85600392612dfa565b14612e8d5750565b6040516335e2f38360e21b81526004810191909152602490fd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480612f98575b15612f02577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a08152612f928161069c565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614612ed9565b604290612fcc612ea7565b906040519161190160f01b8352600283015260228201522090565b604051602081018181106001600160401b038211176106615760405260008152906000368137565b90613019826120c4565b61302660405191826106b7565b8281528092613037601f19916120c4565b0190602036910137565b60ff811461307f5760ff811690601f821161306d576040519161306383610666565b8252602082015290565b604051632cd44ac360e21b8152600490fd5b50604051600554816000613092836103e3565b8083529260019081811690811561311857506001146130b9575b50610aaf925003826106b7565b6005600090815291507f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8483106130fd5750610aaf9350508101602001386130ac565b819350908160209254838589010152019101909184926130e4565b905060209250610aaf94915060ff191682840152151560051b820101386130ac565b60ff811461315c5760ff811690601f821161306d576040519161306383610666565b5060405160065481600061316f836103e3565b8083529260019081811690811561311857506001146131955750610aaf925003826106b7565b6006600090815291507ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8483106131d95750610aaf9350508101602001386130ac565b819350908160209254838589010152019101909184926131c0565b65ffffffffffff90818111613207571690565b604490604051906306dfcc6560e41b8252603060048301526024820152fd5b60001981019190821161139257565b9190820391821161139257565b906001820180921161139257565b9190820180921161139257565b600a80546000816005811161330b575b509290925b8381106132b1575050600091801560001461328f57505050600090565b61329890613226565b9152600080516020615eba833981519152015460301c90565b90928082169080831860011c8201809211611392578360005265ffffffffffff8083600080516020615eba833981519152015416908616106000146132f95750925b90613272565b93915061330590613242565b906132f3565b909161331682613381565b82039182116113925783835265ffffffffffff8083600080516020615eba833981519152015416908616106000146133515750905b3861326d565b915061335c90613242565b61334b565b811561336b570490565b634e487b7160e01b600052601260045260246000fd5b6001811115610aaf57600181600160801b81101561349a575b61344261343861342e61342461341a61341061344e97600488600160401b6134499a101561348d575b640100000000811015613480575b62010000811015613473575b610100811015613467575b601081101561345b575b1015613453575b60030260011c613409818b613361565b0160011c90565b613409818a613361565b6134098189613361565b6134098188613361565b6134098187613361565b6134098186613361565b8093613361565b821190565b900390565b60011b6133f9565b811c9160021b916133f2565b60081c91811b916133e8565b60101c9160081b916133dd565b60201c9160101b916133d1565b60401c9160201b916133c3565b50600160401b9050608082901c61339a565b600a54600090806134be575050600090565b8060001981011161139257600a7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a79252015460301c90565b80546000918161350857505050600090565b6000199282848101116113925760209181522001015460301c90565b91905b8382106135345750505090565b9091928083169080841860011c82018092116113925760008581526020902082015465ffffffffffff90811690841610156135735750925b9190613527565b93925061357f90613242565b9161356c565b1561358c57565b60405162461bcd60e51b815260206004820152602360248201527f4d75737420686f6c6420746f6b656e7320746f206372656174652070726f706f6044820152621cd85b60ea1b6064820152608490fd5b156135e457565b60405162461bcd60e51b815260206004820152601960248201527f4475726174696f6e206d75737420626520706f736974697665000000000000006044820152606490fd5b1561363057565b60405162461bcd60e51b815260206004820152601360248201527210da185a5b881b9bdd081cdd5c1c1bdc9d1959606a1b6044820152606490fd5b1561367257565b60405162461bcd60e51b815260206004820152601060248201526f54696d656c6f636b20746f6f2062696760801b6044820152606490fd5b60001981146113925760010190565b8181106136c4575050565b600081556001016136b9565b90601f82116136dd575050565b61071391600c600052600080516020615e7a833981519152906020601f840160051c83019310613715575b601f0160051c01906136b9565b9091508190613708565b90601f821161372c575050565b61071391600d600052600080516020615eda833981519152906020601f840160051c8301931061371557601f0160051c01906136b9565b90601f8211613770575050565b61071391600e600052600080516020615e9a833981519152906020601f840160051c8301931061371557601f0160051c01906136b9565b90601f82116137b4575050565b61071391600f600052600080516020615f1a833981519152906020601f840160051c8301931061371557601f0160051c01906136b9565b9190601f81116137fa57505050565b610713926000526020600020906020601f840160051c8301931061371557601f0160051c01906136b9565b9081516001600160401b0381116106615761384a81613845600c546103e3565b6136d0565b602080601f8311600114613886575081929360009261387b575b50508160011b916000199060031b1c191617600c55565b015190503880613864565b90601f198316946138a7600c600052600080516020615e7a83398151915290565b926000905b8782106138e45750508360019596106138cb575b505050811b01600c55565b015160001960f88460031b161c191690553880806138c0565b806001859682949686015181550195019301906138ac565b9081516001600160401b038111610661576139218161391c600d546103e3565b61371f565b602080601f831160011461395d5750819293600092613952575b50508160011b916000199060031b1c191617600d55565b01519050388061393b565b90601f1983169461397e600d600052600080516020615eda83398151915290565b926000905b8782106139bb5750508360019596106139a2575b505050811b01600d55565b015160001960f88460031b161c19169055388080613997565b80600185968294968601518155019501930190613983565b9081516001600160401b038111610661576139f8816139f3600e546103e3565b613763565b602080601f8311600114613a345750819293600092613a29575b50508160011b916000199060031b1c191617600e55565b015190503880613a12565b90601f19831694613a55600e600052600080516020615e9a83398151915290565b926000905b878210613a92575050836001959610613a79575b505050811b01600e55565b015160001960f88460031b161c19169055388080613a6e565b80600185968294968601518155019501930190613a5a565b9081516001600160401b03811161066157613acf81613aca600f546103e3565b6137a7565b602080601f8311600114613b0b5750819293600092613b00575b50508160011b916000199060031b1c191617600f55565b015190503880613ae9565b90601f19831694613b2c600f600052600080516020615f1a83398151915290565b926000905b878210613b69575050836001959610613b50575b505050811b01600f55565b015160001960f88460031b161c19169055388080613b45565b80600185968294968601518155019501930190613b31565b91909182516001600160401b03811161066157613ba881613ba284546103e3565b846137eb565b602080601f8311600114613be4575081929394600092613bd9575b50508160011b916000199060031b1c1916179055565b015190503880613bc3565b90601f19831695613bfa85600052602060002090565b926000905b888210613c3757505083600195969710613c1e575b505050811b019055565b015160001960f88460031b161c19169055388080613c14565b80600185968294968601518155019501930190613bff565b80518210156114955760209160051b010190565b15613c6a57565b60405162461bcd60e51b815260206004820152601a60248201527f54617267657420636861696e206e6f7420737570706f727465640000000000006044820152606490fd5b601c54600160401b811015610661576001810180601c5581101561149557601c6000527f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a2110155565b601e54600160401b811015610661576001810180601e5581101561149557601e600052600080516020615efa8339815191520155565b90815491600160401b8310156106615782613d509160016107139501815561149a565b90919082549060031b91821b91600019901b1916179055565b9081526001600160a01b039091166020820152606060408201819052610aaf92910190610957565b604090610aaf9392815281602082015201906114f1565b33600090815260208190526040902092949392909190613dc7906111c8565b613dd28115156135dd565b613dec61117961117285600052601d602052604060002090565b613dfc6301e1338087111561366b565b613e8f60175496613e0f6111e2896136aa565b613e83613e2689600052601b602052604060002090565b97898955613e61600195613e3c88888d01613b81565b600060028c0155600060038c0155613e5b60048c0160ff198154169055565b42613250565b60058a01556006890180546001600160a01b0319163317905560078901613b81565b84600888015542613250565b94600a8101958655613eae613ea3436131f4565b65ffffffffffff1690565b8061401c5750819060005b600b820155600960009101925b613fc7575b505050613fa5613fc1937fdb17271edb72bcaba16ce918d885db2e701491c9ff3f713f80caf9d614aa9ff4613f957ff46a1614ca62096cf230d10ea203eb985f7a60d98cdffc807d794181bc0a9f9a97957f7585f467599d0f008985f231af99293be388626ac16ca59505c2f8f88969cd637f5d1231ca3a274bcd2f510e0d53a889213ebf0315b86ee6bb9d73da08fba7460696613f688c613caf565b8b613f7a604051928392339084613d69565b0390a1604080518b8152602081019290925290918291820190565b0390a16040519182918883613d91565b0390a15460408051858152602081019290925290918291820190565b0390a190565b85518110156140175780613ffd613ff8611172613fe7614011958b613c4f565b51600052601d602052604060002090565b613c63565b611fc561400a8289613c4f565b5185613d2d565b81613ec6565b613ecb565b61402590613226565b908291613eb9565b1561403457565b60405162461bcd60e51b815260206004820152601760248201527f50726f706f73616c20646f6573206e6f742065786973740000000000000000006044820152606490fd5b1561408057565b60405162461bcd60e51b815260206004820152600c60248201526b159bdd1a5b99c8195b99195960a21b6044820152606490fd5b156140bb57565b60405162461bcd60e51b815260206004820152601960248201527f50726f706f73616c20616c7265616479206578656375746564000000000000006044820152606490fd5b1561410757565b60405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e481d9bdd1959609a1b6044820152606490fd5b1561414357565b60405162461bcd60e51b815260206004820152601660248201527557726f6e6720636861696e20666f7220766f74696e6760501b6044820152606490fd5b6002600b5414614192576002600b55565b604051633ee5aeb560e01b8152600490fd5b90600a820291808304600a149015171561139257565b8181029291811591840414171561139257565b9081600052601b6020526141e860406000209283541461402d565b60028201546003830154928382019081831161139257600b015460649061421f906001600160d01b03906113509061134b90612a8c565b04111592839182614231575b50509190565b119050388061422b565b1561424257565b606460405162461bcd60e51b815260206004820152602060248201527f45786563757465206f6e6c7920696e20676f7665726e616e636520636861696e6044820152fd5b1561428d57565b60405162461bcd60e51b815260206004820152602760248201527f566f74696e67206e6f7420656e64656420616e642071756f72756d206e6f74206044820152661c995858da195960ca1b6064820152608490fd5b156142e957565b60405162461bcd60e51b8152602060048201526013602482015272141c9bdc1bdcd85b081b9bdd081c185cdcd959606a1b6044820152606490fd5b1561432b57565b60405162461bcd60e51b8152602060048201526014602482015273151a5b595b1bd8dac81b9bdd08195e1c1a5c995960621b6044820152606490fd5b919082526020916040838201526000928254614382816103e3565b9384604085015260019182811690816000146143e457506001146143a9575b505050505090565b6000908152828120949550935b8585106143d05750505060609250010138808080806143a1565b8054858501606001529382019381016143b6565b93505050506060935060ff929192191683830152151560051b010138808080806143a1565b1561441057565b60405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e48195e1958dd5d195960821b6044820152606490fd5b1561444f57565b60405162461bcd60e51b815260206004820152600e60248201526d27b7363c9034b734ba34b0ba37b960911b6044820152606490fd5b1561448c57565b60405162461bcd60e51b815260206004820152602360248201527f496e73756666696369656e7420766f74696e6720706f77657220746f2063616e60448201526218d95b60ea1b6064820152608490fd5b91926060938192845260406020850152816040850152848401376000828201840152601f01601f1916010190565b1561451257565b60405162461bcd60e51b815260206004820152602760248201527f50726f706f73616c20616c726561647920657865637574656420696e20746869604482015266399031b430b4b760c91b6064820152608490fd5b1561456e57565b60405162461bcd60e51b815260206004820152602760248201527f557365206578656375746550726f706f73616c20696e20676f7665726e616e63604482015266329031b430b4b760c91b6064820152608490fd5b156145ca57565b60405162461bcd60e51b8152602060048201526014602482015273436861696e206e6f7420696e207461726765747360601b6044820152606490fd5b1561460d57565b60405162461bcd60e51b815260206004820152600e60248201526d426164207369676e61747572657360901b6044820152606490fd5b91908110156114955760051b81013590601e1981360301821215610a995701908135916001600160401b038311610a99576020018236038113610a99579190565b91908110156114955760051b0190565b35610aaf81610bc2565b156146a557565b60405162461bcd60e51b815260206004820152600d60248201526c426164207369676e617475726560981b6044820152606490fd5b156146e157565b60405162461bcd60e51b815260206004820152601060248201526f223ab83634b1b0ba329039b4b3b732b960811b6044820152606490fd5b1561472057565b60405162461bcd60e51b815260206004820152601b60248201527f4e6f20766f74696e6720706f77657220617420736e617073686f7400000000006044820152606490fd5b1561476c57565b60405162461bcd60e51b815260206004820152601a60248201527f51756f72756d206e6f74207265616368656420627920736967730000000000006044820152606490fd5b8151610aaf92612d619260401983016147e9576147e292506020820151906060604084015193015160001a90612d6a565b9192909190565b505060009160029190565b61480d600091808352601b60205260408320541461402d565b80601e54915b82811061482257505050600190565b61484261482e8261485b565b600052601d60205260ff6040600020541690565b1561485557614850906136aa565b614813565b50905090565b601e5481101561487e57601e600052600080516020615efa833981519152015490565b60405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840c6d0c2d2dc40d2dcc8caf606b1b6044820152606490fd5b909291926148c68161107f565b916148d460405193846106b7565b829482845282820111610a99576020610713930190610934565b9190604083820312610a995782516001600160e01b031981168103610a9957926020810151906001600160401b038211610a9957019080601f83011215610a99578151610aaf926020016148b9565b90816020910312610a99575190565b9190826040910312610a995760208251920151610aaf81610bc2565b9080601f83011215610a99578151610aaf926020016148b9565b9080601f83011215610a995781519061499a826120c4565b926149a860405194856106b7565b828452602092838086019160051b83010192808411610a9957848301915b8483106149d65750505050505090565b82516001600160401b038111610a995786916149f784848094890101614968565b8152019201916149c6565b91909161010081840312610a99578051916001600160401b0392838111610a995784614a2f918401614968565b936020830151848111610a995781614a48918501614968565b936040840151818111610a995782614a61918601614968565b936060810151828111610a995783614a7a918301614968565b9360808201519360a08301519360c0840151908111610a995760e091614aa1918501614982565b92015190565b614abb6020918280825183010191016148ee565b91906001600160e01b031916630236fce560e51b8103614afa57508181614aeb9261071394518301019101614a02565b96959095949194939293615206565b63f0f9e6b760e01b8103614b2357508181614b1e926107139451830101910161493d565b615304565b632ab43f7f60e11b8103614b4c57508181614b47926107139451830101910161493d565b6153a4565b6304fa45bf60e31b8103614b7f57508181614b70926107139451830101910161494c565b6001600160a01b031690615501565b633972e9fb60e21b8103614ba857508181614ba3926107139451830101910161493d565b6155b1565b63093f734560e31b8103614bd157508181614bcc926107139451830101910161493d565b614c44565b633e78500160e21b8103614bfa57508181614bf5926107139451830101910161493d565b614ddf565b633cdb568760e11b14915061071390505760405162461bcd60e51b81526020600482015260116024820152702ab735b737bbb71037b832b930ba34b7b760791b6044820152606490fd5b80600052601d60205260ff60406000205416614cf2576018548114614cad57614ca881614c9f610cef7fbba9d55e9fd1a441b1617724e2fdb76777d15ec77ab2b72ac15952cbe97085db94600052601d602052604060002090565b6121c581613cf7565b0390a1565b60405162461bcd60e51b815260206004820152601860248201527f43616e6e6f74206164642063757272656e7420636861696e00000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601760248201527f436861696e20616c726561647920737570706f727465640000000000000000006044820152606490fd5b15614d3e57565b60405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f742072656d6f76652063757272656e7420636861696e00000000006044820152606490fd5b601e548015614dc95760001981019080821015611495577f50bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e34f600091601e83520155601e55565b634e487b7160e01b600052603160045260246000fd5b614dff60ff614df883600052601d602052604060002090565b5416613629565b614e0d601854821415614d37565b614e2e614e2482600052601d602052604060002090565b805460ff19169055565b60005b601e5480821015614eb55782614e53614e4984611470565b90549060031b1c90565b14614e675750614e62906136aa565b614e31565b91614ead614ca892613d50614ea7614e49614ea27f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d598613226565b611470565b91611470565b6121c5614d83565b5050614ca87f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d5916121c5565b15614ee857565b60405162461bcd60e51b815260206004820152601660248201527553796d626f6c2063616e6e6f7420626520656d70747960501b6044820152606490fd5b15614f2d57565b60405162461bcd60e51b815260206004820152601860248201527f4c6f636174696f6e2063616e6e6f7420626520656d70747900000000000000006044820152606490fd5b15614f7957565b60405162461bcd60e51b815260206004820152601460248201527324b73b30b634b210353ab934b9b234b1ba34b7b760611b6044820152606490fd5b15614fbc57565b60405162461bcd60e51b815260206004820152600d60248201526c496e76616c6964204f4b544d4f60981b6044820152606490fd5b15614ff857565b60405162461bcd60e51b815260206004820152600b60248201526a0496e76616c6964204b50560ac1b6044820152606490fd5b805190600160401b821161066157601254826012558083106150a3575b5060126000526020908101907fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34446000925b848410615087575050505050565b6001838261509783945186613b81565b01920193019290615079565b600060128152837fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344492830192015b8281106150df575050615048565b806150ec600192546103e3565b806150f9575b50016150d1565b601f9081811184146151115750508281555b386150f2565b836151339261512585600052602060002090565b920160051c820191016136b9565b6000818152602081208183555561510b565b9897969495926151889061517a61516a6151969597948d610100908181520190610957565b6020978d89818403910152610957565b908b820360408d0152610957565b9089820360608b0152610957565b93608088015260a087015285830360c08701528151908184528084019381808460051b8301019401946000915b8483106151d857505050505060e09150930152565b909192939484806151f5600193601f198682030187528a51610957565b9801930193019195949392906151c3565b94909591939692968551156152c8577f62d6efdb8dbca656ac38d327c1d66a4ccaeabc91c464fe5e7352b604858f5f4697614ca89561524789511515614ee1565b61525381511515614f26565b61525e831515614f72565b615269841515614fb5565b615274861515614ff1565b61527d88613825565b615286896138fc565b61528f816139d3565b61529882613aaa565b6152a183601055565b6152aa84601155565b6152b38561502b565b6152bc86601355565b60405198899889615145565b60405162461bcd60e51b81526020600482015260146024820152734e616d652063616e6e6f7420626520656d70747960601b6044820152606490fd5b80151580615399575b156153545760168054908290556040805191825260208201929092527fd0198ea88bf9c4ad5317b68e697944e524541fcb494d854f095b1cd88a097ab69181908101614ca8565b60405162461bcd60e51b815260206004820152601960248201527f496e76616c69642071756f72756d2070657263656e74616765000000000000006044820152606490fd5b50606481111561530d565b80600052601d6020526153be60ff60406000205416613629565b601854908181146154095760188190556040805192835260208301919091527f979103c7afbf0138fe781172504ceb318ff78f9a420de8cabac8141f0121b521919081908101614ca8565b60405162461bcd60e51b815260206004820152600d60248201526c14d85b594818da185a5b881251609a1b6044820152606490fd5b1561544557565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606490fd5b1561548057565b60405162461bcd60e51b81526020600482015260156024820152744d6f64756c6520616c72656164792065786973747360581b6044820152606490fd5b156154c457565b60405162461bcd60e51b8152602060048201526015602482015274135bd91d5b1948191bd95cc81b9bdd08195e1a5cdd605a1b6044820152606490fd5b7ff14475b19484bf096265507cc0c41cd3bf1994992088806830686e2d7272271991906155386001600160a01b038316151561543e565b80600052601a60205261555360ff6040600020541615615479565b600081815260196020526040902080546001600160a01b0319166001600160a01b038416179055601a602090815260406000819020805460ff1916600117905580519283526001600160a01b03909316908201529081908101614ca8565b60207f4c7c76abe482a2c36ea52f1b999474c69f8b4afeeac5635f8aea2526864ba8539180600052601a82526155ee60ff604060002054166154bd565b600081815260198352604080822080546001600160a01b0319169055601a845290819020805460ff1916905551908152a1565b6012549061562e826120c4565b91604061563d815194856106b7565b8184528360208091019160126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444906000935b85851061568157505050505050565b600184819284516156968161292b818a610599565b815201930194019391615672565b9060405191828154918282526020928383019160005283600020936000905b8282106156d957505050610713925003836106b7565b8554845260019586019588955093810193909101906156c3565b601c9081549283821015615792578101918282116113925783831161578a575b818303838111611392576157269061300f565b93825b84811061573857505050505090565b81811015611495576157859083600052807f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a211015461577f6157798784613235565b89613c4f565b526136aa565b615729565b839250615713565b50505050610aaf612fe7565b6157b281600052601b602052604060002090565b906157bf8183541461402d565b600482015460ff8160081c1661586e5760ff16615867576157df906141cd565b60058301544210828115948161585f575b81615850575b506158475782918261582e575b5050615827578161581e575b5061581957600090565b600290565b9050153861580f565b5050600190565b8492509061583f575b503880615803565b905038615837565b50505050600590565b600a91500154421015386157f6565b8391506157f0565b5050600390565b505050600490565b9060005b6009830180548210156158b85761589282849261149a565b90549060031b1c146158b0576158a96009916136aa565b905061587a565b505050600190565b50505050600090565b6001600160a01b0390811692918190841561594d575b16908115615905575b6107139360005260086020528060406000205416916000526040600020541690615992565b61590e83615b1a565b93615918436131f4565b6001600160d01b0395868061592b6134ac565b1691169003958611611392576107139561594491615c04565b505093506158e0565b905061595883615b1a565b90615962436131f4565b6001600160d01b039283806159756134ac565b1691160192831161139257839261598b91615c04565b50506158d7565b6001600160a01b03808316939291908116908185141580615adb575b6159ba575b5050505050565b81615a3f575b5050826159cf575b80806159b3565b6001600160a01b031660009081526009602052604090207fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72491615a1c91615a169091615b1a565b90615ae4565b604080516001600160d01b039384168152919092166020820152a23880806159c8565b6001600160a01b03166000908152600960205260409020615a5f84615b1a565b615a68436131f4565b6001600160d01b03918280615a7c866134f6565b169116900392828411611392577fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72493615ad192615ab892615ced565b6040805192851683529316602082015291829190820190565b0390a238806159c0565b508315156159ae565b90615aee436131f4565b6001600160d01b03918280615b02866134f6565b1691160191821161139257615b1692615ced565b9091565b6001600160d01b0390818111615b2e571690565b604490604051906306dfcc6560e41b825260d060048301526024820152fd5b600a5490600160401b821015610661576001820180600a5582101561149557600a600052805160209091015160301b65ffffffffffff191665ffffffffffff9190911617600080516020615eba83398151915290910155565b8054600160401b81101561066157615bc39160018201815561149a565b615bee57815160209092015160301b65ffffffffffff191665ffffffffffff92909216919091179055565b634e487b7160e01b600052600060045260246000fd5b600a549192918015615cc357615c1c615c3491613226565b600a600052600080516020615eba8339815191520190565b9081549165ffffffffffff90818416918316808311615cb157869203615c7957615c7292509065ffffffffffff82549181199060301b169116179055565b60301c9190565b5050615cac90615c98615c8a611072565b65ffffffffffff9092168252565b6001600160d01b0385166020820152615b4d565b615c72565b604051632520601d60e01b8152600490fd5b50615ce790615cd3615c8a611072565b6001600160d01b0384166020820152615b4d565b60009190565b80549293928015615d8457615d04615d1191613226565b8260005260206000200190565b9182549265ffffffffffff91828516928116808411615cb157879303615d505750615c7292509065ffffffffffff82549181199060301b169116179055565b915050615cac91615d70615d62611072565b65ffffffffffff9093168352565b6001600160d01b0386166020830152615ba6565b5090615ce791615d95615d62611072565b6001600160d01b0385166020830152615ba6565b6001600160a01b03808316929181811690848203615e3e57600082815260086020526040902080546001600160a01b031981166001600160a01b038716179091556107139593169392615e389285907f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f600080a46001600160a01b031660009081526020819052604090205490565b91615992565b60405162461bcd60e51b815260206004820152601360248201527211195b1959d85d1a5bdb88191a5cd8589b1959606a1b6044820152606490fdfedf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7bb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fdc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8d7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb550bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e3508d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802a2646970667358221220342bb23de0ffd74d2c73ab1bca80be5afb39937e0bdb34deb68fe801c38061eb64736f6c63430008140033", + "bytecode": "0x6101608060405234620001f85762007e6f8038038091620000208262000213565b833980820160408212620001f85782516001600160401b0392838211620001f85781906101809182910312620001f8576200005a6200027f565b9082860151858111620001f85784876200007792860101620002f7565b825280830151858111620001f85784876200009592860101620002f7565b60208301526101a0830151858111620001f8578487620000b892860101620002f7565b60408301526101c0830151858111620001f8578487620000db92860101620002f7565b60608301526101e0830151608083015261020083015160a0830152610220830151858111620001f857848762000114928601016200036a565b60c083015261024083015160e0830152610260830151956101009687840152610280840151868111620001f85785826200015192870101620003f5565b9561012096878501526102a0850151818111620001f857868362000178928801016200046c565b9561014096878601526102c0860151918211620001f85782620001a292620001ae9701016200046c565b90830152519062001209565b60405191615d8d938462002082853960805184612dfa015260a05184612eb5015260c05184612dc4015260e05184612e4901525183612e6f015251826118510152518161187d0152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b601f01601f1916610160908101906001600160401b038211908210176200023957604052565b620001fd565b604081019081106001600160401b038211176200023957604052565b601f909101601f19168101906001600160401b038211908210176200023957604052565b6040519061018082016001600160401b038111838210176200023957604052565b6040519061014082016001600160401b038111838210176200023957604052565b60405190620002d0826200023f565b565b60005b838110620002e65750506000910152565b8181015183820152602001620002d5565b81601f82011215620001f85780516001600160401b0381116200023957604051926200032e601f8301601f1916602001856200025b565b81845260208284010111620001f8576200034f9160208085019101620002d2565b90565b6001600160401b038111620002395760051b60200190565b9080601f83011215620001f857815190620003858262000352565b926200039560405194856200025b565b828452602092838086019160051b83010192808411620001f857848301915b848310620003c55750505050505090565b82516001600160401b038111620001f8578691620003e984848094890101620002f7565b815201920191620003b4565b81601f82011215620001f8578051916200040f8362000352565b926200041f60405194856200025b565b808452602092838086019260051b820101928311620001f8578301905b8282106200044b575050505090565b81516001600160a01b0381168103620001f85781529083019083016200043c565b81601f82011215620001f857805191620004868362000352565b926200049660405194856200025b565b808452602092838086019260051b820101928311620001f8578301905b828210620004c2575050505090565b81518152908301908301620004b3565b90600182811c9216801562000504575b6020831014620004ee57565b634e487b7160e01b600052602260045260246000fd5b91607f1691620004e2565b8181106200051b575050565b600081556001016200050f565b90601f821162000536575050565b620002d09160036000526020600020906020601f840160051c8301931062000567575b601f0160051c01906200050f565b909150819062000559565b90601f821162000580575050565b620002d09160046000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f8211620005be575050565b620002d09160056000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f8211620005fc575050565b620002d09160066000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f82116200063a575050565b620002d091600d6000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f821162000678575050565b620002d091600e6000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f8211620006b6575050565b620002d091600f6000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b90601f8211620006f4575050565b620002d091600c6000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b9190601f81116200073457505050565b620002d0926000526020600020906020601f840160051c830193106200056757601f0160051c01906200050f565b80519091906001600160401b03811162000239576200078e8162000788600454620004d2565b62000572565b602080601f8311600114620007cd5750819293600092620007c1575b50508160011b916000199060031b1c191617600455565b015190503880620007aa565b6004600052601f198316949091907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b926000905b8782106200083c57505083600195961062000822575b505050811b01600455565b015160001960f88460031b161c1916905538808062000817565b8060018596829496860151815501950193019062000801565b80519091906001600160401b038111620002395762000881816200087b600d54620004d2565b6200062c565b602080601f8311600114620008c05750819293600092620008b4575b50508160011b916000199060031b1c191617600d55565b0151905038806200089d565b600d600052601f198316949091907fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5926000905b8782106200092f57505083600195961062000915575b505050811b01600d55565b015160001960f88460031b161c191690553880806200090a565b80600185968294968601518155019501930190620008f4565b80519091906001600160401b038111620002395762000974816200096e600e54620004d2565b6200066a565b602080601f8311600114620009b35750819293600092620009a7575b50508160011b916000199060031b1c191617600e55565b01519050388062000990565b600e600052601f198316949091907fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd926000905b87821062000a2257505083600195961062000a08575b505050811b01600e55565b015160001960f88460031b161c19169055388080620009fd565b80600185968294968601518155019501930190620009e7565b80519091906001600160401b038111620002395762000a678162000a61600f54620004d2565b620006a8565b602080601f831160011462000aa6575081929360009262000a9a575b50508160011b916000199060031b1c191617600f55565b01519050388062000a83565b600f600052601f198316949091907f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802926000905b87821062000b1557505083600195961062000afb575b505050811b01600f55565b015160001960f88460031b161c1916905538808062000af0565b8060018596829496860151815501950193019062000ada565b81519192916001600160401b038111620002395762000b5a8162000b538454620004d2565b8462000724565b602080601f831160011462000b9957508192939460009262000b8d575b50508160011b916000199060031b1c1916179055565b01519050388062000b77565b90601f1983169562000bb085600052602060002090565b926000905b88821062000bf05750508360019596971062000bd6575b505050811b019055565b015160001960f88460031b161c1916905538808062000bcc565b8060018596829496860151815501950193019062000bb5565b634e487b7160e01b600052601160045260246000fd5b80519068010000000000000000821162000239576012548260125580831062000c91575b50601260005260209081019060008051602062007e0f8339815191526000925b84841062000c72575050505050565b6001838262000c848394518662000b2e565b0192019301929062000c63565b6012600090815260008051602062007e0f8339815191529182019184015b82811062000cbf57505062000c43565b8062000cce60019254620004d2565b8062000cdd575b500162000caf565b601f90818111841462000cf75750508281555b3862000cd5565b8362000d1c9262000d0d85600052602060002090565b920160051c820191016200050f565b6000818152602081208183555562000cf0565b805180516001600160401b038111620002395762000d5a8162000d54600c54620004d2565b620006e6565b6020918290601f831160011462000e1b5762000dfd938361012094620002d0979462000da89460009262000e0f575b50508160011b916000199060031b1c191617600c555b82015162000855565b62000db7604082015162000948565b62000dc6606082015162000a3b565b608081015160105560a081015160115562000de560c082015162000c1f565b60e08101516013556101008101516014550151151590565b60ff8019601554169115151617601555565b01519050388062000d89565b600c600052601f19831691907fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c79260005b81811062000e9e575084620002d0979462000da89462000dfd9894610120986001951062000e84575b505050811b01600c5562000d9f565b015160001960f88460031b161c1916905538808062000e75565b92938660018192878601518155019501930162000e4c565b600019811462000ec65760010190565b62000c09565b634e487b7160e01b600052603260045260246000fd5b805182101562000ef75760209160051b010190565b62000ecc565b601e546801000000000000000081101562000239576001810180601e5581101562000ef757601e6000527f50bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e3500155565b1562000f5457565b60405162461bcd60e51b815260206004820152601660248201527f417272617973206c656e677468206d69736d61746368000000000000000000006044820152606490fd5b1562000fa157565b60405162461bcd60e51b815260206004820152601360248201527f4e6f20696e697469616c20706172746e657273000000000000000000000000006044820152606490fd5b1562000fee57565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606490fd5b156200102a57565b60405162461bcd60e51b815260206004820152600b60248201526a16995c9bc8185b5bdd5b9d60aa1b6044820152606490fd5b90815180825260208080930193019160005b8281106200107e575050505090565b8351855293810193928101926001016200106f565b9092916040820191604081528451809352606081019260208096019060005b818110620010cf575050506200034f93948184039101526200105d565b82516001600160a01b031686529487019491870191600101620010b2565b906020916200110881518092818552858086019101620002d2565b601f01601f1916010190565b96989a999795926200115d906200114e6200113e6200116c959794610140808d528c0190620010ed565b6020978b8203898d0152620010ed565b9089820360408b0152620010ed565b908782036060890152620010ed565b92608086015260a085015283820360c08501528551908183528083019281808460051b8301019801936000915b848310620011d8575050505050506200034f9495620011c99160e084015261010083019060018060a01b03169052565b6101208184039101526200105d565b9091929394988480620011f8600193601f198682030187528d51620010ed565b9b0193019301919493929062001199565b80519260208201938451816200121f926200146f565b81519284519260408101928351936060830190815194608085019889519660a087019788519060c08901519260e08a019b8c51956200125d620002a0565b9e8f91825260208201526040015260608d015260808c015260a08b015260c08a015260e089015261010042818a0152610120988981016200129e9060019052565b620012a99062000d2f565b85015160165560185560005b61016085018051805183101562001321576200130e83809362001307620012fa620012e96200131b98620013159762000ee2565b51600052601d602052604060002090565b805460ff19166001179055565b5162000ee2565b5162000efd565b62000eb6565b620012b5565b505050929597909396919497860195865151986200134861014083019a8b51511462000f4c565b62001357885151151562000f99565b60005b88518051821015620013d65790620013158c620013c96200139e84620013966200138982620013d09962000ee2565b516001600160a01b031690565b935162000ee2565b51620013b56001600160a01b038416151562000fe6565b620013c281151562001022565b82620015e2565b8062001f92565b6200135a565b5050909192939598977ff9e7aa11bcdcbb8ac33b5dba92fca799ef091e54c29270822065501d8edea1a57f11b248463a1620b36a975da8f250009f56fb5dd0e9d5027a90a834d0ee84d6f6996200146a9799519051906200143d6040519283928362001093565b0390a18251935196519751945190519061016060c0850151935194015195604051998a9930978b62001114565b0390a1565b929190926040519062001482826200023f565b60019283835260209081840194603160f81b865287519060018060401b0382116200023957620014bf82620014b9600354620004d2565b62000528565b8398601f831160011462001555578291620014fc95969798999a839260009462001549575b50501b916000199060031b1c19161760035562000762565b6200150782620016b0565b610120526200151683620017c0565b61014052815191012060e052519020610100524660a0526200153762001925565b6080523060c052620002d06001600b55565b015192503880620014e4565b6003600052601f198316999192917fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9160005b8c8110620015cc575083620014fc9798999a9b9c10620015b2575b505050811b0160035562000762565b015160001960f88460031b161c19169055388080620015a3565b8183015184559285019291870191870162001588565b91906001600160a01b0383168015620016975760025482810180911162000ec6576002556001600160a01b038416600090815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a3600254926001600160d01b0384116200166d57620002d092935062001991565b604051630e58ae9360e11b8152600481018590526001600160d01b036024820152604490fd5b0390fd5b60405163ec442f0560e01b815260006004820152602490fd5b9081516020808210600014620016ce575050906200034f90620018d0565b6001600160401b0382116200023957620016f582620016ef600554620004d2565b620005b0565b80601f831160011462001735575081929360009262001729575b50508160011b916000199060031b1c19161760055560ff90565b0151905038806200170f565b6005600052601f198316949091907f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0926000905b878210620017a75750508360019596106200178d575b505050811b0160055560ff90565b015160001960f88460031b161c191690553880806200177f565b8060018596829496860151815501950193019062001769565b9081516020808210600014620017de575050906200034f90620018d0565b6001600160401b03821162000239576200180582620017ff600654620004d2565b620005ee565b80601f831160011462001845575081929360009262001839575b50508160011b916000199060031b1c19161760065560ff90565b0151905038806200181f565b6006600052601f198316949091907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f926000905b878210620018b75750508360019596106200189d575b505050811b0160065560ff90565b015160001960f88460031b161c191690553880806200188f565b8060018596829496860151815501950193019062001879565b601f815111620018fe576020815191015160208210620018ee571790565b6000198260200360031b1b161790565b60405163305a27a960e01b81526020600482015290819062001693906024830190620010ed565b60e051610100516040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815260c0810181811060018060401b03821117620002395760405251902090565b906200199d8162001ccd565b9165ffffffffffff80431162001a7b57600a5460008162001a48575050620019d990620019d0620002d09560006200204d565b90431662001dc9565b50506001600160a01b0390811690811562001a2b575b60086020527f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c75460009283526040909220548116911662001a9a565b62001a4062001a3a8462001ccd565b62001c18565b5050620019ef565b60009291921995838781011162000ec657620002d096620019d994602084600a620019d096522001015460301c6200204d565b6040516306dfcc6560e41b815260306004820152436024820152604490fd5b6001600160a01b0380831693929190811690818514158062001c0e575b62001ac4575b5050505050565b8162001b40575b50508262001adc575b808062001abd565b6001600160a01b0316600090815260096020526040902060008051602062007e4f8339815191529162001b1c9162001b15909162001ccd565b9062001c75565b604080516001600160d01b039384168152919092166020820152a238808062001ad4565b6001600160a01b0316600090815260096020526040902062001b628462001ccd565b9065ffffffffffff9081431162001a7b57805460008162001bcf5750509062001bac9162001ba260008051602062007e4f83398151915294600062002067565b9143169062001ec5565b604080516001600160d01b039384168152919092166020820152a2388062001acb565b6000939291931994848681011162000ec65760008051602062007e4f8339815191529562001bac956020848662001ba296522001015460301c62002067565b5083151562001ab7565b65ffffffffffff80431162001a7b57600a5460008162001c49575050620019d062001c4592600062002067565b9091565b9092600019848181011162000ec65762001c4594602084600a620019d096522001015460301c62002067565b65ffffffffffff9081431162001a7b57805460008162001ca257505062001ba262001c459360006200204d565b9093600019858181011162000ec65762001c45956020848662001ba296522001015460301c6200204d565b6001600160d01b039081811162001ce2571690565b604490604051906306dfcc6560e41b825260d060048301526024820152fd5b60001981019190821162000ec657565b600a54906801000000000000000082101562000239576001820180600a5582101562000ef757600a60005280516020919091015160301b65ffffffffffff191665ffffffffffff919091161760008051602062007e2f83398151915290910155565b9081546801000000000000000081101562000239576001810180845581101562000ef75760009283526020928390208251929093015160301b65ffffffffffff191665ffffffffffff9290921691909117910155565b600a54919291801562001e965762001de562001dfe9162001d01565b600a60005260008051602062007e2f8339815191520190565b9081549165ffffffffffff9081841691831680831162001e845786920362001e465762001e3f92509065ffffffffffff82549181199060301b169116179055565b60301c9190565b505062001e7e9062001e6962001e5b620002c1565b65ffffffffffff9092168252565b6001600160d01b038516602082015262001d11565b62001e3f565b604051632520601d60e01b8152600490fd5b5062001ebf9062001eaa62001e5b620002c1565b6001600160d01b038416602082015262001d11565b60009190565b8054929392801562001f685762001ee062001eed9162001d01565b8260005260206000200190565b9182549265ffffffffffff9182851692811680841162001e845787930362001f2f575062001e3f92509065ffffffffffff82549181199060301b169116179055565b91505062001e7e9162001f5362001f45620002c1565b65ffffffffffff9093168352565b6001600160d01b038616602083015262001d73565b509062001ebf9162001f7d62001f45620002c1565b6001600160d01b038516602083015262001d73565b6001600160a01b039081169180821691828403620020085760008481526008602052604080822080546001600160a01b031981168717909155620002d096931694909285907f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f8480a48060205220549162001a9a565b60405162461bcd60e51b815260206004820152601360248201527f44656c65676174696f6e2064697361626c6564000000000000000000000000006044820152606490fd5b6001600160d01b039182169082160190811162000ec65790565b6001600160d01b039182169082160390811162000ec6579056fe6080604052600436101561001257600080fd5b60003560e01c8063013cf08b146103de57806306fdde03146103d9578063078f6208146103d4578063095ea7b3146103cf5780630c0512e9146103ca5780630d61b519146103c557806318160ddd146103c0578063204c5d1f146103bb57806322dbefbb1461030c57806322f3e2d4146103b657806323b872dd146103b15780632519ae5c146103ac578063313ce567146103a75780633644e515146103a25780633a46b1a8146102d557806347c661401461039d5780634b145793146103075780634bf5d7e9146103985780634cf2ab32146103935780634cfd16bb1461038e5780634de184f6146103845780634fa76ec9146103895780635221c1f014610384578063548d496f1461037f578063587cde1e1461037a5780635c19a95c146103755780635cf0e8a4146103705780636cbadbfa146103705780636dcf811d1461036b5780636fcfff451461036657806370a08231146103615780637ce288ea1461035c5780637e5a9b47146103575780637ecebe00146103525780637f6dda141461034d57806384b0196e1461034857806385e59ce2146103435780638e539e8c1461033e5780639080936f1461033957806391ddadf41461033457806395d89b411461032f57806398e527d31461032a5780639a49bdde146103255780639ab24eb014610320578063a351f6151461031b578063a9059cbb14610316578063adf7420714610311578063b0b6cc1a1461030c578063b3fe8bcb14610307578063c3cda52014610302578063c8a6d06e146102fd578063c97bfe6b146102f8578063c9a3c0c7146102f3578063c9d27afe146102ee578063d505accf146102e9578063dcf628c0146102e4578063dd62ed3e146102df578063e49a62e9146102da578063eaeded5f146102d5578063eced3dfb146102d0578063f1127ed8146102cb5763f2c26a47146102c657600080fd5b6127d5565b6126af565b612691565b61126b565b612673565b612610565b612578565b6123ce565b612281565b612191565b612140565b6120b8565b611f76565b61132c565b610f20565b611c76565b611c1c565b611ae4565b611a9b565b611a7d565b611a5f565b6119b8565b61198c565b611963565b611931565b6118fa565b611838565b611802565b6117c5565b611797565b61170c565b6116cf565b611662565b61163f565b611621565b6115f9565b6115ba565b611589565b611534565b61156b565b6114ba565b611447565b61135d565b611296565b611248565b61122c565b6110c7565b610f8b565b610f54565b610e3d565b610d0d565b610c17565b610bf9565b610bc4565b610b84565b610aa3565b6109ec565b90600182811c92168015610413575b60208310146103fd57565b634e487b7160e01b600052602260045260246000fd5b91607f16916103f2565b600d546000929161042d826103e3565b80825291600190818116908115610492575060011461044b57505050565b91929350600d600052600080516020615cf8833981519152916000925b84841061047a57505060209250010190565b80546020858501810191909152909301928101610468565b915050602093945060ff929192191683830152151560051b010190565b600e54600092916104bf826103e3565b8082529160019081811690811561049257506001146104dd57505050565b91929350600e600052600080516020615cb8833981519152916000925b84841061050c57505060209250010190565b805460208585018101919091529093019281016104fa565b600f5460009291610534826103e3565b80825291600190818116908115610492575060011461055257505050565b91929350600f600052600080516020615d38833981519152916000925b84841061058157505060209250010190565b8054602085850181019190915290930192810161056f565b90600092918054916105aa836103e3565b91828252600193848116908160001461060c57506001146105cc575b50505050565b90919394506000526020928360002092846000945b8386106105f85750505050010190388080806105c6565b8054858701830152940193859082016105e1565b9294505050602093945060ff191683830152151560051b010190388080806105c6565b634e487b7160e01b600052604160045260246000fd5b61014081019081106001600160401b0382111761066157604052565b61062f565b604081019081106001600160401b0382111761066157604052565b60a081019081106001600160401b0382111761066157604052565b60c081019081106001600160401b0382111761066157604052565b90601f801991011681019081106001600160401b0382111761066157604052565b60405190600082600c54916106ec836103e3565b808352926001908181169081156107625750600114610715575b50610713925003836106b7565b565b600c60009081529150600080516020615c988339815191525b8483106107475750610713935050810160200138610706565b81935090816020925483858a0101520191019091859261072e565b90506020925061071394915060ff191682840152151560051b82010138610706565b60405190600082600d5491610798836103e3565b8083529260019081811690811561076257506001146107be5750610713925003836106b7565b600d60009081529150600080516020615cf88339815191525b8483106107f05750610713935050810160200138610706565b81935090816020925483858a010152019101909185926107d7565b60405190600082600e549161081f836103e3565b8083529260019081811690811561076257506001146108455750610713925003836106b7565b600e60009081529150600080516020615cb88339815191525b8483106108775750610713935050810160200138610706565b81935090816020925483858a0101520191019091859261085e565b60405190600082600f54916108a6836103e3565b8083529260019081811690811561076257506001146108cc5750610713925003836106b7565b600f60009081529150600080516020615d388339815191525b8483106108fe5750610713935050810160200138610706565b81935090816020925483858a010152019101909185926108e5565b9061071361092d9260405193848092610599565b03836106b7565b60005b8381106109475750506000910152565b8181015183820152602001610937565b9060209161097081518092818552858086019101610934565b601f01601f1916010190565b97936109a56109e1989497936101409b97939e9d9c9e8b526101608060208d01528b0190610957565b60408a0197909752606089015215156080880152151560a087015260c08601526001600160a01b031660e0850152838203610100850152610957565b946101208201520152565b34610a8a576020366003190112610a8a57600435600052601b60205260406000208054610a8660405191610a2e83610a278160018801610599565b03846106b7565b600284015460038501546004860154600587015460068801549397929492936001600160a01b031691610a6360078601610919565b93600a6008870154960154966040519a8b9a60ff808660081c169516938c61097c565b0390f35b600080fd5b906020610aa0928181520190610957565b90565b34610a8a57600080600319360112610b81576040519080600354610ac6816103e3565b80855291600191808316908115610b575750600114610afc575b610a8685610af0818703826106b7565b60405191829182610a8f565b9250600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b828410610b3f575050508101602001610af082610a86610ae0565b80546020858701810191909152909301928101610b24565b869550610a8696935060209250610af094915060ff191682840152151560051b8201019293610ae0565b80fd5b34610a8a576000366003190112610a8a576060601654601854601e549060405192835260208301526040820152f35b6001600160a01b03811603610a8a57565b34610a8a576040366003190112610a8a57610bee600435610be481610bb3565b6024359033612b0f565b602060405160018152f35b34610a8a576000366003190112610a8a576020601754604051908152f35b34610a8a576020366003190112610a8a577fbadbd87941bb6424ed4aa4719bf01a3319b64480e49f89018c718603239553d260043580600052601b60205260076040600020610c6883825414613eb3565b610cd760048201610c89610c84610c80835460ff1690565b1590565b613f3a565b610c9a6018546008850154146140c1565b610cca610ca686614053565b60058601544210801590610d06575b610cbe9061410c565b81610cfe575b50614168565b805460ff19166001179055565b0190610cea610ce583610919565b6148ea565b610cf9604051928392836141aa565b0390a1005b905038610cc4565b5080610cb5565b34610a8a576000366003190112610a8a576020600254604051908152f35b90815180825260208092019182818360051b85019501936000915b848310610d565750505050505090565b9091929394958480610d7083856001950387528a51610957565b9801930193019194939290610d46565b610aa090602081528251610e18610da561014092836020860152610160850190610957565b610def610ddb610dc7602089015193601f1994858983030160408a0152610957565b604089015184888303016060890152610957565b606088015183878303016080880152610957565b90608087015160a086015260a087015160c086015260c0870151908583030160e0860152610d2b565b9360e08101516101009081850152810151906101209182850152015191019015159052565b34610a8a57600080600319360112610b8157610a8690610f14604051610e6281610645565b60609283825283602083015283604083015283808301528060808301528060a08301528360c08301528060e083015261010090808284015261012080930152610ea9611040565b93610eb26106d8565b8552610ebc610784565b6020860152610ec961080b565b6040860152610ed6610892565b90850152601054608085015260115460a0850152610ef261545a565b60c085015260135460e08501526014549084015260155460ff16151590830152565b60405191829182610d80565b34610a8a576020366003190112610a8a576004356000526019602052602060018060a01b0360406000205416604051908152f35b34610a8a576000366003190112610a8a5760ff601f54161580610f7f575b6020906040519015158152f35b5060155460ff16610f72565b34610a8a576060366003190112610a8a57600435610fa881610bb3565b602435610fb481610bb3565b6001600160a01b03821660009081526001602090815260408083203384529091529020604435919054926000198410610ffe575b610ff293506129fd565b60405160018152602090f35b82841061101a5761101583610ff295033383612bc3565b610fe8565b604051637dc7a0d960e11b81523360048201526024810185905260448101849052606490fd5b6040519061071382610645565b6040519061071382610666565b6001600160401b03811161066157601f01601f191660200190565b9291926110818261105a565b9161108f60405193846106b7565b829481845281830111610a8a578281602093846000960137010152565b9080601f83011215610a8a57816020610aa093359101611075565b34610a8a5760a0366003190112610a8a576004356001600160401b038111610a8a576110f79036906004016110ac565b6064359060443561110783610bb3565b6111c26084359161113461112f61112885600052601d602052604060002090565b5460ff1690565b6134f7565b6111486001600160a01b0386161515615277565b61116a611165610c8061112884600052601a602052604060002090565b6152b2565b336000908152602081905260409020611186905b54151561349f565b6040516304fa45bf60e31b602082015260248101919091526001600160a01b03909416604485015283606481015b03601f1981018552846106b7565b601e54926111cf84612f29565b9360005b8181106111fd57610a866111ed338887876024358b613cc4565b6040519081529081906020820190565b8061121761120d61122793611405565b90549060031b1c90565b6112218289613b6b565b526135c6565b6111d3565b34610a8a576000366003190112610a8a57602060405160128152f35b34610a8a576000366003190112610a8a576020611263612dc1565b604051908152f35b34610a8a576040366003190112610a8a57602061126360043561128d81610bb3565b602435906128ec565b34610a8a576020366003190112610a8a5760043580600052601b6020526112c4604060002091825414613eb3565b60646112ef60018060d01b036112e56112e0600a8601546129a6565b613177565b1660165490614040565b049060036002820154910154918282019081831161132757604080519384526020840194909452928201526060810191909152608090f35b6129e7565b34610a8a576020366003190112610a8a57600435600052601a602052602060ff604060002054166040519015158152f35b34610a8a576000366003190112610a8a576113774361310e565b65ffffffffffff806113884361310e565b169116036113dd57610a8660405161139f81610666565b601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c740000006020820152604051918291602083526020830190610957565b6040516301bfc1c560e61b8152600490fd5b634e487b7160e01b600052603260045260246000fd5b601e5481101561142a57601e600052600080516020615d188339815191520190600090565b6113ef565b805482101561142a5760005260206000200190600090565b34610a8a576020366003190112610a8a57600435601e54811015610a8a57602090601e600052600080516020615d188339815191520154604051908152f35b90815180825260208080930193019160005b8281106114a6575050505090565b835185529381019392810192600101611498565b34610a8a576000366003190112610a8a5760405180601e54808252826020809301601e600052600080516020615d188339815191529260005b8582821061151e5750505061150a925003836106b7565b610a86604051928284938452830190611486565b85548452600195860195889550930192016114f3565b34610a8a576020366003190112610a8a576020611561600435600052601d60205260ff6040600020541690565b6040519015158152f35b34610a8a576000366003190112610a8a576020601654604051908152f35b34610a8a576020366003190112610a8a57600435600052601d602052602060ff604060002054166040519015158152f35b34610a8a576020366003190112610a8a5760206004356115d981610bb3565b60018060a01b038091166000526008825260406000205416604051908152f35b34610a8a576020366003190112610a8a5761161f60043561161981610bb3565b33615bc7565b005b34610a8a576000366003190112610a8a576020601854604051908152f35b34610a8a576000366003190112610a8a57602060ff601f54166040519015158152f35b34610a8a576020366003190112610a8a5760043561167f81610bb3565b6001600160a01b031660009081526009602052604090205463ffffffff908181116116b05760209160405191168152f35b604490604051906306dfcc6560e41b8252602060048301526024820152fd5b34610a8a576020366003190112610a8a5760206112636004356116f181610bb3565b6001600160a01b031660009081526020819052604090205490565b34610a8a576020366003190112610a8a5760043561172981614637565b1561175b5760207f57df5a6a467271f04b10f7fe9e66d21dcd8ae7eaf079099d48959f24a53b691091604051908152a1005b60405162461bcd60e51b81526020600482015260146024820152734e6f7420616c6c20636861696e7320726561647960601b6044820152606490fd5b34610a8a576020366003190112610a8a5760406117b5600435614053565b8251911515825215156020820152f35b34610a8a576020366003190112610a8a576004356117e281610bb3565b60018060a01b031660005260076020526020604060002054604051908152f35b34610a8a576040366003190112610a8a57610a8661182460243560043561552c565b604051918291602083526020830190611486565b34610a8a576000366003190112610a8a576118cb6118757f0000000000000000000000000000000000000000000000000000000000000000612f5b565b610a866118a17f0000000000000000000000000000000000000000000000000000000000000000613054565b6118d96118ac612f01565b91604051958695600f60f81b875260e0602088015260e0870190610957565b908582036040870152610957565b90466060850152306080850152600060a085015283820360c0850152611486565b34610a8a576020366003190112610a8a57602060646119286001600160d01b036112e56112e06004356129a6565b04604051908152f35b34610a8a576020366003190112610a8a5760206001600160d01b0361195a6112e06004356129a6565b16604051908152f35b34610a8a576020366003190112610a8a5760206119816004356155d1565b60ff60405191168152f35b34610a8a576000366003190112610a8a5760206119a84361310e565b65ffffffffffff60405191168152f35b34610a8a57600080600319360112610b815760405190806004546119db816103e3565b80855291600191808316908115610b575750600114611a0457610a8685610af0818703826106b7565b9250600483527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b828410611a47575050508101602001610af082610a86610ae0565b80546020858701810191909152909301928101611a2c565b34610a8a576000366003190112610a8a576020601c54604051908152f35b34610a8a576020366003190112610a8a57602061126360043561469e565b34610a8a576020366003190112610a8a57600435611ab881610bb3565b6001600160a01b031660009081526009602090815260409091206001600160d01b039061195a90613410565b34610a8a576040366003190112610a8a576004356001600160401b03602435818111610a8a5736602382011215610a8a578060040135918211610a8a573660248383010111610a8a57610cf9602492847fc7c129e53e59dadfa16305619e80c7519f1f6912c10915359fd75b56bcecdd7b95600052601b602052611c0e6040600020611b7283825414613eb3565b611bff600a6004830192611b92611b8d610c80865460ff1690565b61424c565b611ba160058201544210613eff565b6006810154611bcb90611bc4906001600160a01b03165b6001600160a01b031690565b331461428b565b0154611bf8611bda82336128ec565b916001600160d01b0390611bf1906112e0906129a6565b169161402a565b10156142c8565b805461ff001916610100179055565b604051948594019084614320565b34610a8a576040366003190112610a8a57610bee600435611c3c81610bb3565b60243590336129fd565b9181601f84011215610a8a578235916001600160401b038311610a8a576020808501948460051b010111610a8a57565b34610a8a576060366003190112610a8a576001600160401b03600435602435828111610a8a57611caa903690600401611c46565b92604435908111610a8a5783611cc584923690600401611c46565b611ccd614007565b611ce184600052601b602052604060002090565b90611cee85835414613eb3565b6004820192611d09611d04610c80865460ff1690565b61434e565b60185494611d1d60088501548714156143aa565b611d2f611d2a8786615694565b614406565b611d3a838214614449565b611dc4876007860197611dbc600a611d518b610919565b6020815191012098015497611dae896040519485936020850197889094939260809260a08301967f45de75acfcd4cbcc5691559486749bf0d5eb65e4b24c59ac2f258ba6bfceaa3484526020840152604083015260608201520152565b03601f1981018352826106b7565b519020612edb565b9760009889945b838610611e8c575050507fda7dba8f94d70cde423cce3a243bebf95d2ec927507b566f67e329dcfe2d06bb877fbadbd87941bb6424ed4aa4719bf01a3319b64480e49f89018c718603239553d2611e6589611e4c8a610cca8f611e45611e3e8e6112e56112e060018060d01b03926129a6565b6064900490565b11156145a8565b611e58610ce582610919565b60405191829185836141aa565b0390a1601854604080519283526020830191909152819081015b0390a161161f6001600b55565b909192939499868b611ec8611bb8611ec3611ebb611eb5611eae868a8f614486565b3691611075565b896145f4565b938a8a6144c7565b6144d7565b6001600160a01b03821690611ede9082146144e1565b8d88886000925b8310611f21575050505091611f00611f1192611f17946128ec565b90611f0c82151561455c565b61316a565b9a6135c6565b9493929190611dcb565b8394955092611f3d611bb8611ec385611f4495611f49986144c7565b141561451d565b6135c6565b90899291888f8990611ee5565b6064359060ff82168203610a8a57565b6084359060ff82168203610a8a57565b34610a8a5760c0366003190112610a8a57600435611f9381610bb3565b60443590602435611fa2611f56565b83421161202a5761201e61161f94612025926040519060208201927fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf845260018060a01b038816604084015286606084015260808301526080825261200682610681565b61201960a4359360843593519020612edb565b612c6c565b9182612c16565b615bc7565b604051632341d78760e11b815260048101859052602490fd5b6001600160401b0381116106615760051b60200190565b81601f82011215610a8a5780359161207183612043565b9261207f60405194856106b7565b808452602092838086019260051b820101928311610a8a578301905b8282106120a9575050505090565b8135815290830190830161209b565b34610a8a5760c0366003190112610a8a576001600160401b03600435818111610a8a576120e99036906004016110ac565b90604435818111610a8a5736602382011215610a8a57612113903690602481600401359101611075565b608435918211610a8a57610a86926121326111ed93369060040161205a565b916064359160243590613539565b34610a8a576020366003190112610a8a57600435601c54811015610a8a57602090601c6000527f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a2110154604051908152f35b34610a8a576080366003190112610a8a576004356001600160401b038111610a8a576121c46111b49136906004016110ac565b604435612241606435916121e861112f61112885600052601d602052604060002090565b61220761220261112883600052601a602052604060002090565b6152f6565b33600090815260208190526040902061221f9061117e565b604051633972e9fb60e21b602082015260248101919091529384906044820190565b601e549261224e84612f29565b9360005b81811061226c57610a866111ed338887876024358b613cc4565b8061121761120d61227c93611405565b612252565b34610a8a576040366003190112610a8a576004356024358015158103610a8a577f78975aaf742630489badd22949b88ac50eaaea576339ee05440b671a33bfb6a9916122cb614007565b611e7f6122e282600052601b602052604060002090565b6122ee83825414613eb3565b6122fd60058201544210613eff565b612311610c84610c80600484015460ff1690565b600b81019061234061233b610c8061112833869060018060a01b0316600052602052604060002090565b613f86565b612351601854600883015414613fc2565b612379610cca612365600a840154336128ec565b336000908152602095909552604090942090565b84156123b95760020161238d82825461316a565b90555b604080519384523360208501529315159383019390935260608201929092529081906080820190565b6003016123c782825461316a565b9055612390565b34610a8a5760e0366003190112610a8a576004356123eb81610bb3565b6024356123f781610bb3565b60443590606435612406611f66565b8142116124f1576001600160a01b0385811660008181526007602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99281019283529283019390935292861660608201526080810187905260a081019190915260c0808201949094529283526124aa92909161249760e0836106b7565b61201960c4359360a43593519020612edb565b6001600160a01b03848116908216036124c7575061161f92612b0f565b6040516325c0072360e11b81526001600160a01b0391821660048201529084166024820152604490fd5b60405163313c898160e11b815260048101839052602490fd5b97949161252f90610aa09c9a97949b9895928a526101608060208c01528a0190610957565b604089019a909a52606088015215156080870152151560a086015260c08501526001600160a01b031660e084015261010083015261012082015280830361014090910152611486565b34610a8a576020366003190112610a8a5760043580600052601b60205260406000206125a78154928314613eb3565b610a86600282015492600383015490600484015460058501546125d3600687015460018060a01b031690565b90600887015492600a880154946125f860096125f160018c01610919565b9a016154dd565b966040519a8b9a60ff808660081c169516938c61250a565b34610a8a576040366003190112610a8a57602061266a60043561263281610bb3565b6024359061263f82610bb3565b60018060a01b03166000526001835260406000209060018060a01b0316600052602052604060002090565b54604051908152f35b34610a8a576020366003190112610a8a576020611561600435614637565b34610a8a576000366003190112610a8a576020601e54604051908152f35b34610a8a576040366003190112610a8a576004356126cc81610bb3565b6024359063ffffffff82168203610a8a57610a869161271c916126ed612bfd565b506126f6612bfd565b506001600160a01b03166000908152600960205260409020612716612bfd565b5061142f565b506040519061272a82610666565b5465ffffffffffff811680835260309190911c60209283019081526040805192835290516001600160d01b031692820192909252918291820190565b9794999895926127ab9061279d6127b99461278f6101009b98958d610120908181520190610957565b8c810360208e015290610957565b908a820360408c0152610957565b9088820360608a0152610957565b97608087015260a086015260c085015260e08401521515910152565b34610a8a57600080600319360112610b8157604051908181600c546127f9816103e3565b808452936001918083169081156128c8575060011461287d575b5050612821925003826106b7565b604051906128328261092d8161041d565b610a8660405161284c81612845816104af565b03826106b7565b60405161285c8161284581610524565b601054601154601354916014549360ff6015541695604051998a998a612766565b9150600c8252600080516020615c988339815191525b8483106128ad575061282193505081016020013880612813565b81935090816020925483858901015201910190918492612893565b9150506020925061282194915060ff191682840152151560051b8201013880612813565b6001600160a01b03166000908152600960205260408120909161290e906129a6565b81549083829160058411612957575b61292893508461343e565b8061293c5750505b6001600160d01b031690565b9161294960209293613140565b92815220015460301c612930565b91926129628161329b565b8103908111611327576129289385875265ffffffffffff808360208a200154169085161060001461299457509161291d565b9291506129a09061315c565b9061291d565b65ffffffffffff6129b64361310e565b16808210156129c95750610aa09061310e565b6044925060405191637669fc0f60e11b835260048301526024820152fd5b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0380821694939291908515612af65782168015612add576001600160a01b03821660009081526020819052604090205495848710612aae5784610713969703612a5f8460018060a01b03166000526000602052604060002090565b556001600160a01b0384166000908152602081815260409182902080548801905590518681527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a36156df565b60405163391434e360e21b81526001600160a01b03841660048201526024810188905260448101869052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b6001600160a01b038082169291908315612baa578216938415612b915780612b877f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92594612b7060209560018060a01b03166000526001602052604060002090565b9060018060a01b0316600052602052604060002090565b55604051908152a3565b604051634a1406b160e11b815260006004820152602490fd5b60405163e602df0560e01b815260006004820152602490fd5b906001600160a01b0380831615612baa57811615612b9157612b70612bfa9260018060a01b03166000526001602052604060002090565b55565b60405190612c0a82610666565b60006020838281520152565b6001600160a01b03811660009081526007602052604090208054600181019091559091819003612c44575050565b6040516301d4b62360e61b81526001600160a01b039092166004830152602482015260449150fd5b91610aa09391612c7b93612c84565b90929192612d34565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612d0857926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612cfc5780516001600160a01b03811615612cf357918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b60041115612d1e57565b634e487b7160e01b600052602160045260246000fd5b612d3d81612d14565b80612d46575050565b612d4f81612d14565b60018103612d695760405163f645eedf60e01b8152600490fd5b612d7281612d14565b60028103612d935760405163fce698f760e01b815260048101839052602490fd5b80612d9f600392612d14565b14612da75750565b6040516335e2f38360e21b81526004810191909152602490fd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480612eb2575b15612e1c577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a08152612eac8161069c565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614612df3565b604290612ee6612dc1565b906040519161190160f01b8352600283015260228201522090565b604051602081018181106001600160401b038211176106615760405260008152906000368137565b90612f3382612043565b612f4060405191826106b7565b8281528092612f51601f1991612043565b0190602036910137565b60ff8114612f995760ff811690601f8211612f875760405191612f7d83610666565b8252602082015290565b604051632cd44ac360e21b8152600490fd5b50604051600554816000612fac836103e3565b808352926001908181169081156130325750600114612fd3575b50610aa0925003826106b7565b6005600090815291507f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8483106130175750610aa0935050810160200138612fc6565b81935090816020925483858901015201910190918492612ffe565b905060209250610aa094915060ff191682840152151560051b82010138612fc6565b60ff81146130765760ff811690601f8211612f875760405191612f7d83610666565b50604051600654816000613089836103e3565b8083529260019081811690811561303257506001146130af5750610aa0925003826106b7565b6006600090815291507ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8483106130f35750610aa0935050810160200138612fc6565b819350908160209254838589010152019101909184926130da565b65ffffffffffff90818111613121571690565b604490604051906306dfcc6560e41b8252603060048301526024820152fd5b60001981019190821161132757565b9190820391821161132757565b906001820180921161132757565b9190820180921161132757565b600a805460008160058111613225575b509290925b8381106131cb57505060009180156000146131a957505050600090565b6131b290613140565b9152600080516020615cd8833981519152015460301c90565b90928082169080831860011c8201809211611327578360005265ffffffffffff8083600080516020615cd8833981519152015416908616106000146132135750925b9061318c565b93915061321f9061315c565b9061320d565b90916132308261329b565b82039182116113275783835265ffffffffffff8083600080516020615cd88339815191520154169086161060001461326b5750905b38613187565b91506132769061315c565b613265565b8115613285570490565b634e487b7160e01b600052601260045260246000fd5b6001811115610aa057600181600160801b8110156133b4575b61335c61335261334861333e61333461332a61336897600488600160401b6133639a10156133a7575b64010000000081101561339a575b6201000081101561338d575b610100811015613381575b6010811015613375575b101561336d575b60030260011c613323818b61327b565b0160011c90565b613323818a61327b565b613323818961327b565b613323818861327b565b613323818761327b565b613323818661327b565b809361327b565b821190565b900390565b60011b613313565b811c9160021b9161330c565b60081c91811b91613302565b60101c9160081b916132f7565b60201c9160101b916132eb565b60401c9160201b916132dd565b50600160401b9050608082901c6132b4565b600a54600090806133d8575050600090565b8060001981011161132757600a7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a79252015460301c90565b80546000918161342257505050600090565b6000199282848101116113275760209181522001015460301c90565b91905b83821061344e5750505090565b9091928083169080841860011c82018092116113275760008581526020902082015465ffffffffffff908116908416101561348d5750925b9190613441565b9392506134999061315c565b91613486565b156134a657565b60405162461bcd60e51b815260206004820152602360248201527f4d75737420686f6c6420746f6b656e7320746f206372656174652070726f706f6044820152621cd85b60ea1b6064820152608490fd5b156134fe57565b60405162461bcd60e51b815260206004820152601360248201527210da185a5b881b9bdd081cdd5c1c1bdc9d1959606a1b6044820152606490fd5b92909391336000526000602052613556604060002054151561349f565b841561358157610aa09482600052601d60205261357a60ff604060002054166134f7565b3394613cc4565b60405162461bcd60e51b815260206004820152601960248201527f4475726174696f6e206d75737420626520706f736974697665000000000000006044820152606490fd5b60001981146113275760010190565b8181106135e0575050565b600081556001016135d5565b90601f82116135f9575050565b61071391600c600052600080516020615c98833981519152906020601f840160051c83019310613631575b601f0160051c01906135d5565b9091508190613624565b90601f8211613648575050565b61071391600d600052600080516020615cf8833981519152906020601f840160051c8301931061363157601f0160051c01906135d5565b90601f821161368c575050565b61071391600e600052600080516020615cb8833981519152906020601f840160051c8301931061363157601f0160051c01906135d5565b90601f82116136d0575050565b61071391600f600052600080516020615d38833981519152906020601f840160051c8301931061363157601f0160051c01906135d5565b9190601f811161371657505050565b610713926000526020600020906020601f840160051c8301931061363157601f0160051c01906135d5565b9081516001600160401b0381116106615761376681613761600c546103e3565b6135ec565b602080601f83116001146137a25750819293600092613797575b50508160011b916000199060031b1c191617600c55565b015190503880613780565b90601f198316946137c3600c600052600080516020615c9883398151915290565b926000905b8782106138005750508360019596106137e7575b505050811b01600c55565b015160001960f88460031b161c191690553880806137dc565b806001859682949686015181550195019301906137c8565b9081516001600160401b0381116106615761383d81613838600d546103e3565b61363b565b602080601f8311600114613879575081929360009261386e575b50508160011b916000199060031b1c191617600d55565b015190503880613857565b90601f1983169461389a600d600052600080516020615cf883398151915290565b926000905b8782106138d75750508360019596106138be575b505050811b01600d55565b015160001960f88460031b161c191690553880806138b3565b8060018596829496860151815501950193019061389f565b9081516001600160401b038111610661576139148161390f600e546103e3565b61367f565b602080601f83116001146139505750819293600092613945575b50508160011b916000199060031b1c191617600e55565b01519050388061392e565b90601f19831694613971600e600052600080516020615cb883398151915290565b926000905b8782106139ae575050836001959610613995575b505050811b01600e55565b015160001960f88460031b161c1916905538808061398a565b80600185968294968601518155019501930190613976565b9081516001600160401b038111610661576139eb816139e6600f546103e3565b6136c3565b602080601f8311600114613a275750819293600092613a1c575b50508160011b916000199060031b1c191617600f55565b015190503880613a05565b90601f19831694613a48600f600052600080516020615d3883398151915290565b926000905b878210613a85575050836001959610613a6c575b505050811b01600f55565b015160001960f88460031b161c19169055388080613a61565b80600185968294968601518155019501930190613a4d565b91909182516001600160401b03811161066157613ac481613abe84546103e3565b84613707565b602080601f8311600114613b00575081929394600092613af5575b50508160011b916000199060031b1c1916179055565b015190503880613adf565b90601f19831695613b1685600052602060002090565b926000905b888210613b5357505083600195969710613b3a575b505050811b019055565b015160001960f88460031b161c19169055388080613b30565b80600185968294968601518155019501930190613b1b565b805182101561142a5760209160051b010190565b15613b8657565b60405162461bcd60e51b815260206004820152601a60248201527f54617267657420636861696e206e6f7420737570706f727465640000000000006044820152606490fd5b601c54600160401b811015610661576001810180601c5581101561142a57601c6000527f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a2110155565b601e54600160401b811015610661576001810180601e5581101561142a57601e600052600080516020615d188339815191520155565b90815491600160401b8310156106615782613c6c9160016107139501815561142f565b90919082549060031b91821b91600019901b1916179055565b9081526001600160a01b039091166020820152606060408201819052610aa092910190610957565b604090610aa0939281528160208201520190611486565b91949060175495613cdc613cd7886135c6565b601755565b613d59613cf388600052601b602052604060002090565b91888355613d2e600194613d0988878701613a9d565b6000600286015560006003860155613d286004860160ff198154169055565b4261316a565b60058401556006830180546001600160a01b0319166001600160a01b03871617905560078301613a9d565b846008820155613d76613d6b4361310e565b65ffffffffffff1690565b80613ea25750819060005b600a820155600960009101925b613e4d575b505050613e37613e47937f7585f467599d0f008985f231af99293be388626ac16ca59505c2f8f88969cd637f5d1231ca3a274bcd2f510e0d53a889213ebf0315b86ee6bb9d73da08fba7460696947fdb17271edb72bcaba16ce918d885db2e701491c9ff3f713f80caf9d614aa9ff494613e0c8a613bcb565b613e1c6040519283928c84613c85565b0390a160408051888152602081019290925290918291820190565b0390a16040519182918583613cad565b0390a190565b8651811015613e9d5780613e83613e7e611128613e6d613e97958c613b6b565b51600052601d602052604060002090565b613b7f565b611f44613e90828a613b6b565b5185613c49565b81613d8e565b613d93565b613eab90613140565b908291613d81565b15613eba57565b60405162461bcd60e51b815260206004820152601760248201527f50726f706f73616c20646f6573206e6f742065786973740000000000000000006044820152606490fd5b15613f0657565b60405162461bcd60e51b815260206004820152600c60248201526b159bdd1a5b99c8195b99195960a21b6044820152606490fd5b15613f4157565b60405162461bcd60e51b815260206004820152601960248201527f50726f706f73616c20616c7265616479206578656375746564000000000000006044820152606490fd5b15613f8d57565b60405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e481d9bdd1959609a1b6044820152606490fd5b15613fc957565b60405162461bcd60e51b815260206004820152601660248201527557726f6e6720636861696e20666f7220766f74696e6760501b6044820152606490fd5b6002600b5414614018576002600b55565b604051633ee5aeb560e01b8152600490fd5b90600a820291808304600a149015171561132757565b8181029291811591840414171561132757565b9081600052601b60205261406e604060002092835414613eb3565b60028201546003830154928382019081831161132757600a01546064906140a5906001600160d01b03906112e5906112e0906129a6565b041115928391826140b7575b50509190565b11905038806140b1565b156140c857565b606460405162461bcd60e51b815260206004820152602060248201527f45786563757465206f6e6c7920696e20676f7665726e616e636520636861696e6044820152fd5b1561411357565b60405162461bcd60e51b815260206004820152602760248201527f566f74696e67206e6f7420656e64656420616e642071756f72756d206e6f74206044820152661c995858da195960ca1b6064820152608490fd5b1561416f57565b60405162461bcd60e51b8152602060048201526013602482015272141c9bdc1bdcd85b081b9bdd081c185cdcd959606a1b6044820152606490fd5b9190825260209160408382015260009282546141c5816103e3565b93846040850152600191828116908160001461422757506001146141ec575b505050505090565b6000908152828120949550935b8585106142135750505060609250010138808080806141e4565b8054858501606001529382019381016141f9565b93505050506060935060ff929192191683830152151560051b010138808080806141e4565b1561425357565b60405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e48195e1958dd5d195960821b6044820152606490fd5b1561429257565b60405162461bcd60e51b815260206004820152600e60248201526d27b7363c9034b734ba34b0ba37b960911b6044820152606490fd5b156142cf57565b60405162461bcd60e51b815260206004820152602360248201527f496e73756666696369656e7420766f74696e6720706f77657220746f2063616e60448201526218d95b60ea1b6064820152608490fd5b91926060938192845260406020850152816040850152848401376000828201840152601f01601f1916010190565b1561435557565b60405162461bcd60e51b815260206004820152602760248201527f50726f706f73616c20616c726561647920657865637574656420696e20746869604482015266399031b430b4b760c91b6064820152608490fd5b156143b157565b60405162461bcd60e51b815260206004820152602760248201527f557365206578656375746550726f706f73616c20696e20676f7665726e616e63604482015266329031b430b4b760c91b6064820152608490fd5b1561440d57565b60405162461bcd60e51b8152602060048201526014602482015273436861696e206e6f7420696e207461726765747360601b6044820152606490fd5b1561445057565b60405162461bcd60e51b815260206004820152600e60248201526d426164207369676e61747572657360901b6044820152606490fd5b919081101561142a5760051b81013590601e1981360301821215610a8a5701908135916001600160401b038311610a8a576020018236038113610a8a579190565b919081101561142a5760051b0190565b35610aa081610bb3565b156144e857565b60405162461bcd60e51b815260206004820152600d60248201526c426164207369676e617475726560981b6044820152606490fd5b1561452457565b60405162461bcd60e51b815260206004820152601060248201526f223ab83634b1b0ba329039b4b3b732b960811b6044820152606490fd5b1561456357565b60405162461bcd60e51b815260206004820152601b60248201527f4e6f20766f74696e6720706f77657220617420736e617073686f7400000000006044820152606490fd5b156145af57565b60405162461bcd60e51b815260206004820152601a60248201527f51756f72756d206e6f74207265616368656420627920736967730000000000006044820152606490fd5b8151610aa092612c7b92604019830161462c5761462592506020820151906060604084015193015160001a90612c84565b9192909190565b505060009160029190565b614650600091808352601b602052604083205414613eb3565b80601e54915b82811061466557505050600190565b6146856146718261469e565b600052601d60205260ff6040600020541690565b1561469857614693906135c6565b614656565b50905090565b601e548110156146c157601e600052600080516020615d18833981519152015490565b60405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840c6d0c2d2dc40d2dcc8caf606b1b6044820152606490fd5b909291926147098161105a565b9161471760405193846106b7565b829482845282820111610a8a576020610713930190610934565b9190604083820312610a8a5782516001600160e01b031981168103610a8a57926020810151906001600160401b038211610a8a57019080601f83011215610a8a578151610aa0926020016146fc565b90816020910312610a8a575190565b9190826040910312610a8a5760208251920151610aa081610bb3565b9080601f83011215610a8a578151610aa0926020016146fc565b9080601f83011215610a8a578151906147dd82612043565b926147eb60405194856106b7565b828452602092838086019160051b83010192808411610a8a57848301915b8483106148195750505050505090565b82516001600160401b038111610a8a57869161483a848480948901016147ab565b815201920191614809565b91909161010081840312610a8a578051916001600160401b0392838111610a8a57846148729184016147ab565b936020830151848111610a8a578161488b9185016147ab565b936040840151818111610a8a57826148a49186016147ab565b936060810151828111610a8a57836148bd9183016147ab565b9360808201519360a08301519360c0840151908111610a8a5760e0916148e49185016147c5565b92015190565b6148fe602091828082518301019101614731565b91906001600160e01b031916630236fce560e51b810361493d5750818161492e9261071394518301019101614845565b9695909594919493929361503f565b63f0f9e6b760e01b8103614966575081816149619261071394518301019101614780565b61513d565b632ab43f7f60e11b810361498f5750818161498a9261071394518301019101614780565b6151dd565b6304fa45bf60e31b81036149c2575081816149b3926107139451830101910161478f565b6001600160a01b03169061533a565b633972e9fb60e21b81036149eb575081816149e69261071394518301019101614780565b6153ea565b63093f734560e31b8103614a1457508181614a0f9261071394518301019101614780565b614a87565b633e78500160e21b8103614a3d57508181614a389261071394518301019101614780565b614c22565b633cdb568760e11b14915061071390505760405162461bcd60e51b81526020600482015260116024820152702ab735b737bbb71037b832b930ba34b7b760791b6044820152606490fd5b80600052601d60205260ff60406000205416614b35576018548114614af057614aeb81614ae2610cca7fbba9d55e9fd1a441b1617724e2fdb76777d15ec77ab2b72ac15952cbe97085db94600052601d602052604060002090565b6111ed81613c13565b0390a1565b60405162461bcd60e51b815260206004820152601860248201527f43616e6e6f74206164642063757272656e7420636861696e00000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601760248201527f436861696e20616c726561647920737570706f727465640000000000000000006044820152606490fd5b15614b8157565b60405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f742072656d6f76652063757272656e7420636861696e00000000006044820152606490fd5b601e548015614c0c576000198101908082101561142a577f50bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e34f600091601e83520155601e55565b634e487b7160e01b600052603160045260246000fd5b614c4260ff614c3b83600052601d602052604060002090565b54166134f7565b614c50601854821415614b7a565b614c71614c6782600052601d602052604060002090565b805460ff19169055565b60005b601e5480821015614cee5782614c8c61120d84611405565b14614ca05750614c9b906135c6565b614c74565b91614ce6614aeb92613c6c614ce061120d614cdb7f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d598613140565b611405565b91611405565b6111ed614bc6565b5050614aeb7f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d5916111ed565b15614d2157565b60405162461bcd60e51b815260206004820152601660248201527553796d626f6c2063616e6e6f7420626520656d70747960501b6044820152606490fd5b15614d6657565b60405162461bcd60e51b815260206004820152601860248201527f4c6f636174696f6e2063616e6e6f7420626520656d70747900000000000000006044820152606490fd5b15614db257565b60405162461bcd60e51b815260206004820152601460248201527324b73b30b634b210353ab934b9b234b1ba34b7b760611b6044820152606490fd5b15614df557565b60405162461bcd60e51b815260206004820152600d60248201526c496e76616c6964204f4b544d4f60981b6044820152606490fd5b15614e3157565b60405162461bcd60e51b815260206004820152600b60248201526a0496e76616c6964204b50560ac1b6044820152606490fd5b805190600160401b82116106615760125482601255808310614edc575b5060126000526020908101907fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34446000925b848410614ec0575050505050565b60018382614ed083945186613a9d565b01920193019290614eb2565b600060128152837fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344492830192015b828110614f18575050614e81565b80614f25600192546103e3565b80614f32575b5001614f0a565b601f908181118414614f4a5750508281555b38614f2b565b83614f6c92614f5e85600052602060002090565b920160051c820191016135d5565b60008181526020812081835555614f44565b989796949592614fc190614fb3614fa3614fcf9597948d610100908181520190610957565b6020978d89818403910152610957565b908b820360408d0152610957565b9089820360608b0152610957565b93608088015260a087015285830360c08701528151908184528084019381808460051b8301019401946000915b84831061501157505050505060e09150930152565b9091929394848061502e600193601f198682030187528a51610957565b980193019301919594939290614ffc565b9490959193969296855115615101577f62d6efdb8dbca656ac38d327c1d66a4ccaeabc91c464fe5e7352b604858f5f4697614aeb9561508089511515614d1a565b61508c81511515614d5f565b615097831515614dab565b6150a2841515614dee565b6150ad861515614e2a565b6150b688613741565b6150bf89613818565b6150c8816138ef565b6150d1826139c6565b6150da83601055565b6150e384601155565b6150ec85614e64565b6150f586601355565b60405198899889614f7e565b60405162461bcd60e51b81526020600482015260146024820152734e616d652063616e6e6f7420626520656d70747960601b6044820152606490fd5b801515806151d2575b1561518d5760168054908290556040805191825260208201929092527fd0198ea88bf9c4ad5317b68e697944e524541fcb494d854f095b1cd88a097ab69181908101614aeb565b60405162461bcd60e51b815260206004820152601960248201527f496e76616c69642071756f72756d2070657263656e74616765000000000000006044820152606490fd5b506064811115615146565b80600052601d6020526151f760ff604060002054166134f7565b601854908181146152425760188190556040805192835260208301919091527f979103c7afbf0138fe781172504ceb318ff78f9a420de8cabac8141f0121b521919081908101614aeb565b60405162461bcd60e51b815260206004820152600d60248201526c14d85b594818da185a5b881251609a1b6044820152606490fd5b1561527e57565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606490fd5b156152b957565b60405162461bcd60e51b81526020600482015260156024820152744d6f64756c6520616c72656164792065786973747360581b6044820152606490fd5b156152fd57565b60405162461bcd60e51b8152602060048201526015602482015274135bd91d5b1948191bd95cc81b9bdd08195e1a5cdd605a1b6044820152606490fd5b7ff14475b19484bf096265507cc0c41cd3bf1994992088806830686e2d7272271991906153716001600160a01b0383161515615277565b80600052601a60205261538c60ff60406000205416156152b2565b600081815260196020526040902080546001600160a01b0319166001600160a01b038416179055601a602090815260406000819020805460ff1916600117905580519283526001600160a01b03909316908201529081908101614aeb565b60207f4c7c76abe482a2c36ea52f1b999474c69f8b4afeeac5635f8aea2526864ba8539180600052601a825261542760ff604060002054166152f6565b600081815260198352604080822080546001600160a01b0319169055601a845290819020805460ff1916905551908152a1565b6012549061546782612043565b916040615476815194856106b7565b8184528360208091019160126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444906000935b8585106154ba57505050505050565b600184819284516154cf81612845818a610599565b8152019301940193916154ab565b9060405191828154918282526020928383019160005283600020936000905b82821061551257505050610713925003836106b7565b8554845260019586019588955093810193909101906154fc565b601c90815492838210156155c557810191828211611327578383116155bd575b8183038381116113275761555f90612f29565b93825b84811061557157505050505090565b8181101561142a576155b89083600052807f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a21101546112216155b2878461314f565b89613b6b565b615562565b83925061554c565b50505050610aa0612f01565b6155e581600052601b602052604060002090565b6155f182825414613eb3565b600481015460ff8160081c1661568c5760ff1661568557615613600592614053565b9290910154421091821592828061567e575b6156755782918261565c575b5050615655578161564c575b5061564757600090565b600290565b9050153861563d565b5050600190565b8492509061566d575b503880615631565b905038615665565b50505050600590565b5081615625565b5050600390565b505050600490565b9060005b6009830180548210156156d6576156b082849261142f565b90549060031b1c146156ce576156c76009916135c6565b9050615698565b505050600190565b50505050600090565b6001600160a01b0390811692918190841561576b575b16908115615723575b61071393600052600860205280604060002054169160005260406000205416906157b0565b61572c83615938565b936157364361310e565b6001600160d01b039586806157496133c6565b1691169003958611611327576107139561576291615a22565b505093506156fe565b905061577683615938565b906157804361310e565b6001600160d01b039283806157936133c6565b169116019283116113275783926157a991615a22565b50506156f5565b6001600160a01b038083169392919081169081851415806158f9575b6157d8575b5050505050565b8161585d575b5050826157ed575b80806157d1565b6001600160a01b031660009081526009602052604090207fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7249161583a916158349091615938565b90615902565b604080516001600160d01b039384168152919092166020820152a23880806157e6565b6001600160a01b0316600090815260096020526040902061587d84615938565b6158864361310e565b6001600160d01b0391828061589a86613410565b169116900392828411611327577fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724936158ef926158d692615b0b565b6040805192851683529316602082015291829190820190565b0390a238806157de565b508315156157cc565b9061590c4361310e565b6001600160d01b0391828061592086613410565b169116019182116113275761593492615b0b565b9091565b6001600160d01b039081811161594c571690565b604490604051906306dfcc6560e41b825260d060048301526024820152fd5b600a5490600160401b821015610661576001820180600a5582101561142a57600a600052805160209091015160301b65ffffffffffff191665ffffffffffff9190911617600080516020615cd883398151915290910155565b8054600160401b811015610661576159e19160018201815561142f565b615a0c57815160209092015160301b65ffffffffffff191665ffffffffffff92909216919091179055565b634e487b7160e01b600052600060045260246000fd5b600a549192918015615ae157615a3a615a5291613140565b600a600052600080516020615cd88339815191520190565b9081549165ffffffffffff90818416918316808311615acf57869203615a9757615a9092509065ffffffffffff82549181199060301b169116179055565b60301c9190565b5050615aca90615ab6615aa861104d565b65ffffffffffff9092168252565b6001600160d01b038516602082015261596b565b615a90565b604051632520601d60e01b8152600490fd5b50615b0590615af1615aa861104d565b6001600160d01b038416602082015261596b565b60009190565b80549293928015615ba257615b22615b2f91613140565b8260005260206000200190565b9182549265ffffffffffff91828516928116808411615acf57879303615b6e5750615a9092509065ffffffffffff82549181199060301b169116179055565b915050615aca91615b8e615b8061104d565b65ffffffffffff9093168352565b6001600160d01b03861660208301526159c4565b5090615b0591615bb3615b8061104d565b6001600160d01b03851660208301526159c4565b6001600160a01b03808316929181811690848203615c5c57600082815260086020526040902080546001600160a01b031981166001600160a01b038716179091556107139593169392615c569285907f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f600080a46001600160a01b031660009081526020819052604090205490565b916157b0565b60405162461bcd60e51b815260206004820152601360248201527211195b1959d85d1a5bdb88191a5cd8589b1959606a1b6044820152606490fdfedf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7bb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fdc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8d7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb550bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e3508d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802a26469706673582212205eddae3f70083f1206f843d74c1dd42c83bc9cd2672ae776335ecdaef553d72464736f6c63430008140033bb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444c65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724", + "deployedBytecode": "0x6080604052600436101561001257600080fd5b60003560e01c8063013cf08b146103de57806306fdde03146103d9578063078f6208146103d4578063095ea7b3146103cf5780630c0512e9146103ca5780630d61b519146103c557806318160ddd146103c0578063204c5d1f146103bb57806322dbefbb1461030c57806322f3e2d4146103b657806323b872dd146103b15780632519ae5c146103ac578063313ce567146103a75780633644e515146103a25780633a46b1a8146102d557806347c661401461039d5780634b145793146103075780634bf5d7e9146103985780634cf2ab32146103935780634cfd16bb1461038e5780634de184f6146103845780634fa76ec9146103895780635221c1f014610384578063548d496f1461037f578063587cde1e1461037a5780635c19a95c146103755780635cf0e8a4146103705780636cbadbfa146103705780636dcf811d1461036b5780636fcfff451461036657806370a08231146103615780637ce288ea1461035c5780637e5a9b47146103575780637ecebe00146103525780637f6dda141461034d57806384b0196e1461034857806385e59ce2146103435780638e539e8c1461033e5780639080936f1461033957806391ddadf41461033457806395d89b411461032f57806398e527d31461032a5780639a49bdde146103255780639ab24eb014610320578063a351f6151461031b578063a9059cbb14610316578063adf7420714610311578063b0b6cc1a1461030c578063b3fe8bcb14610307578063c3cda52014610302578063c8a6d06e146102fd578063c97bfe6b146102f8578063c9a3c0c7146102f3578063c9d27afe146102ee578063d505accf146102e9578063dcf628c0146102e4578063dd62ed3e146102df578063e49a62e9146102da578063eaeded5f146102d5578063eced3dfb146102d0578063f1127ed8146102cb5763f2c26a47146102c657600080fd5b6127d5565b6126af565b612691565b61126b565b612673565b612610565b612578565b6123ce565b612281565b612191565b612140565b6120b8565b611f76565b61132c565b610f20565b611c76565b611c1c565b611ae4565b611a9b565b611a7d565b611a5f565b6119b8565b61198c565b611963565b611931565b6118fa565b611838565b611802565b6117c5565b611797565b61170c565b6116cf565b611662565b61163f565b611621565b6115f9565b6115ba565b611589565b611534565b61156b565b6114ba565b611447565b61135d565b611296565b611248565b61122c565b6110c7565b610f8b565b610f54565b610e3d565b610d0d565b610c17565b610bf9565b610bc4565b610b84565b610aa3565b6109ec565b90600182811c92168015610413575b60208310146103fd57565b634e487b7160e01b600052602260045260246000fd5b91607f16916103f2565b600d546000929161042d826103e3565b80825291600190818116908115610492575060011461044b57505050565b91929350600d600052600080516020615cf8833981519152916000925b84841061047a57505060209250010190565b80546020858501810191909152909301928101610468565b915050602093945060ff929192191683830152151560051b010190565b600e54600092916104bf826103e3565b8082529160019081811690811561049257506001146104dd57505050565b91929350600e600052600080516020615cb8833981519152916000925b84841061050c57505060209250010190565b805460208585018101919091529093019281016104fa565b600f5460009291610534826103e3565b80825291600190818116908115610492575060011461055257505050565b91929350600f600052600080516020615d38833981519152916000925b84841061058157505060209250010190565b8054602085850181019190915290930192810161056f565b90600092918054916105aa836103e3565b91828252600193848116908160001461060c57506001146105cc575b50505050565b90919394506000526020928360002092846000945b8386106105f85750505050010190388080806105c6565b8054858701830152940193859082016105e1565b9294505050602093945060ff191683830152151560051b010190388080806105c6565b634e487b7160e01b600052604160045260246000fd5b61014081019081106001600160401b0382111761066157604052565b61062f565b604081019081106001600160401b0382111761066157604052565b60a081019081106001600160401b0382111761066157604052565b60c081019081106001600160401b0382111761066157604052565b90601f801991011681019081106001600160401b0382111761066157604052565b60405190600082600c54916106ec836103e3565b808352926001908181169081156107625750600114610715575b50610713925003836106b7565b565b600c60009081529150600080516020615c988339815191525b8483106107475750610713935050810160200138610706565b81935090816020925483858a0101520191019091859261072e565b90506020925061071394915060ff191682840152151560051b82010138610706565b60405190600082600d5491610798836103e3565b8083529260019081811690811561076257506001146107be5750610713925003836106b7565b600d60009081529150600080516020615cf88339815191525b8483106107f05750610713935050810160200138610706565b81935090816020925483858a010152019101909185926107d7565b60405190600082600e549161081f836103e3565b8083529260019081811690811561076257506001146108455750610713925003836106b7565b600e60009081529150600080516020615cb88339815191525b8483106108775750610713935050810160200138610706565b81935090816020925483858a0101520191019091859261085e565b60405190600082600f54916108a6836103e3565b8083529260019081811690811561076257506001146108cc5750610713925003836106b7565b600f60009081529150600080516020615d388339815191525b8483106108fe5750610713935050810160200138610706565b81935090816020925483858a010152019101909185926108e5565b9061071361092d9260405193848092610599565b03836106b7565b60005b8381106109475750506000910152565b8181015183820152602001610937565b9060209161097081518092818552858086019101610934565b601f01601f1916010190565b97936109a56109e1989497936101409b97939e9d9c9e8b526101608060208d01528b0190610957565b60408a0197909752606089015215156080880152151560a087015260c08601526001600160a01b031660e0850152838203610100850152610957565b946101208201520152565b34610a8a576020366003190112610a8a57600435600052601b60205260406000208054610a8660405191610a2e83610a278160018801610599565b03846106b7565b600284015460038501546004860154600587015460068801549397929492936001600160a01b031691610a6360078601610919565b93600a6008870154960154966040519a8b9a60ff808660081c169516938c61097c565b0390f35b600080fd5b906020610aa0928181520190610957565b90565b34610a8a57600080600319360112610b81576040519080600354610ac6816103e3565b80855291600191808316908115610b575750600114610afc575b610a8685610af0818703826106b7565b60405191829182610a8f565b9250600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b828410610b3f575050508101602001610af082610a86610ae0565b80546020858701810191909152909301928101610b24565b869550610a8696935060209250610af094915060ff191682840152151560051b8201019293610ae0565b80fd5b34610a8a576000366003190112610a8a576060601654601854601e549060405192835260208301526040820152f35b6001600160a01b03811603610a8a57565b34610a8a576040366003190112610a8a57610bee600435610be481610bb3565b6024359033612b0f565b602060405160018152f35b34610a8a576000366003190112610a8a576020601754604051908152f35b34610a8a576020366003190112610a8a577fbadbd87941bb6424ed4aa4719bf01a3319b64480e49f89018c718603239553d260043580600052601b60205260076040600020610c6883825414613eb3565b610cd760048201610c89610c84610c80835460ff1690565b1590565b613f3a565b610c9a6018546008850154146140c1565b610cca610ca686614053565b60058601544210801590610d06575b610cbe9061410c565b81610cfe575b50614168565b805460ff19166001179055565b0190610cea610ce583610919565b6148ea565b610cf9604051928392836141aa565b0390a1005b905038610cc4565b5080610cb5565b34610a8a576000366003190112610a8a576020600254604051908152f35b90815180825260208092019182818360051b85019501936000915b848310610d565750505050505090565b9091929394958480610d7083856001950387528a51610957565b9801930193019194939290610d46565b610aa090602081528251610e18610da561014092836020860152610160850190610957565b610def610ddb610dc7602089015193601f1994858983030160408a0152610957565b604089015184888303016060890152610957565b606088015183878303016080880152610957565b90608087015160a086015260a087015160c086015260c0870151908583030160e0860152610d2b565b9360e08101516101009081850152810151906101209182850152015191019015159052565b34610a8a57600080600319360112610b8157610a8690610f14604051610e6281610645565b60609283825283602083015283604083015283808301528060808301528060a08301528360c08301528060e083015261010090808284015261012080930152610ea9611040565b93610eb26106d8565b8552610ebc610784565b6020860152610ec961080b565b6040860152610ed6610892565b90850152601054608085015260115460a0850152610ef261545a565b60c085015260135460e08501526014549084015260155460ff16151590830152565b60405191829182610d80565b34610a8a576020366003190112610a8a576004356000526019602052602060018060a01b0360406000205416604051908152f35b34610a8a576000366003190112610a8a5760ff601f54161580610f7f575b6020906040519015158152f35b5060155460ff16610f72565b34610a8a576060366003190112610a8a57600435610fa881610bb3565b602435610fb481610bb3565b6001600160a01b03821660009081526001602090815260408083203384529091529020604435919054926000198410610ffe575b610ff293506129fd565b60405160018152602090f35b82841061101a5761101583610ff295033383612bc3565b610fe8565b604051637dc7a0d960e11b81523360048201526024810185905260448101849052606490fd5b6040519061071382610645565b6040519061071382610666565b6001600160401b03811161066157601f01601f191660200190565b9291926110818261105a565b9161108f60405193846106b7565b829481845281830111610a8a578281602093846000960137010152565b9080601f83011215610a8a57816020610aa093359101611075565b34610a8a5760a0366003190112610a8a576004356001600160401b038111610a8a576110f79036906004016110ac565b6064359060443561110783610bb3565b6111c26084359161113461112f61112885600052601d602052604060002090565b5460ff1690565b6134f7565b6111486001600160a01b0386161515615277565b61116a611165610c8061112884600052601a602052604060002090565b6152b2565b336000908152602081905260409020611186905b54151561349f565b6040516304fa45bf60e31b602082015260248101919091526001600160a01b03909416604485015283606481015b03601f1981018552846106b7565b601e54926111cf84612f29565b9360005b8181106111fd57610a866111ed338887876024358b613cc4565b6040519081529081906020820190565b8061121761120d61122793611405565b90549060031b1c90565b6112218289613b6b565b526135c6565b6111d3565b34610a8a576000366003190112610a8a57602060405160128152f35b34610a8a576000366003190112610a8a576020611263612dc1565b604051908152f35b34610a8a576040366003190112610a8a57602061126360043561128d81610bb3565b602435906128ec565b34610a8a576020366003190112610a8a5760043580600052601b6020526112c4604060002091825414613eb3565b60646112ef60018060d01b036112e56112e0600a8601546129a6565b613177565b1660165490614040565b049060036002820154910154918282019081831161132757604080519384526020840194909452928201526060810191909152608090f35b6129e7565b34610a8a576020366003190112610a8a57600435600052601a602052602060ff604060002054166040519015158152f35b34610a8a576000366003190112610a8a576113774361310e565b65ffffffffffff806113884361310e565b169116036113dd57610a8660405161139f81610666565b601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c740000006020820152604051918291602083526020830190610957565b6040516301bfc1c560e61b8152600490fd5b634e487b7160e01b600052603260045260246000fd5b601e5481101561142a57601e600052600080516020615d188339815191520190600090565b6113ef565b805482101561142a5760005260206000200190600090565b34610a8a576020366003190112610a8a57600435601e54811015610a8a57602090601e600052600080516020615d188339815191520154604051908152f35b90815180825260208080930193019160005b8281106114a6575050505090565b835185529381019392810192600101611498565b34610a8a576000366003190112610a8a5760405180601e54808252826020809301601e600052600080516020615d188339815191529260005b8582821061151e5750505061150a925003836106b7565b610a86604051928284938452830190611486565b85548452600195860195889550930192016114f3565b34610a8a576020366003190112610a8a576020611561600435600052601d60205260ff6040600020541690565b6040519015158152f35b34610a8a576000366003190112610a8a576020601654604051908152f35b34610a8a576020366003190112610a8a57600435600052601d602052602060ff604060002054166040519015158152f35b34610a8a576020366003190112610a8a5760206004356115d981610bb3565b60018060a01b038091166000526008825260406000205416604051908152f35b34610a8a576020366003190112610a8a5761161f60043561161981610bb3565b33615bc7565b005b34610a8a576000366003190112610a8a576020601854604051908152f35b34610a8a576000366003190112610a8a57602060ff601f54166040519015158152f35b34610a8a576020366003190112610a8a5760043561167f81610bb3565b6001600160a01b031660009081526009602052604090205463ffffffff908181116116b05760209160405191168152f35b604490604051906306dfcc6560e41b8252602060048301526024820152fd5b34610a8a576020366003190112610a8a5760206112636004356116f181610bb3565b6001600160a01b031660009081526020819052604090205490565b34610a8a576020366003190112610a8a5760043561172981614637565b1561175b5760207f57df5a6a467271f04b10f7fe9e66d21dcd8ae7eaf079099d48959f24a53b691091604051908152a1005b60405162461bcd60e51b81526020600482015260146024820152734e6f7420616c6c20636861696e7320726561647960601b6044820152606490fd5b34610a8a576020366003190112610a8a5760406117b5600435614053565b8251911515825215156020820152f35b34610a8a576020366003190112610a8a576004356117e281610bb3565b60018060a01b031660005260076020526020604060002054604051908152f35b34610a8a576040366003190112610a8a57610a8661182460243560043561552c565b604051918291602083526020830190611486565b34610a8a576000366003190112610a8a576118cb6118757f0000000000000000000000000000000000000000000000000000000000000000612f5b565b610a866118a17f0000000000000000000000000000000000000000000000000000000000000000613054565b6118d96118ac612f01565b91604051958695600f60f81b875260e0602088015260e0870190610957565b908582036040870152610957565b90466060850152306080850152600060a085015283820360c0850152611486565b34610a8a576020366003190112610a8a57602060646119286001600160d01b036112e56112e06004356129a6565b04604051908152f35b34610a8a576020366003190112610a8a5760206001600160d01b0361195a6112e06004356129a6565b16604051908152f35b34610a8a576020366003190112610a8a5760206119816004356155d1565b60ff60405191168152f35b34610a8a576000366003190112610a8a5760206119a84361310e565b65ffffffffffff60405191168152f35b34610a8a57600080600319360112610b815760405190806004546119db816103e3565b80855291600191808316908115610b575750600114611a0457610a8685610af0818703826106b7565b9250600483527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b828410611a47575050508101602001610af082610a86610ae0565b80546020858701810191909152909301928101611a2c565b34610a8a576000366003190112610a8a576020601c54604051908152f35b34610a8a576020366003190112610a8a57602061126360043561469e565b34610a8a576020366003190112610a8a57600435611ab881610bb3565b6001600160a01b031660009081526009602090815260409091206001600160d01b039061195a90613410565b34610a8a576040366003190112610a8a576004356001600160401b03602435818111610a8a5736602382011215610a8a578060040135918211610a8a573660248383010111610a8a57610cf9602492847fc7c129e53e59dadfa16305619e80c7519f1f6912c10915359fd75b56bcecdd7b95600052601b602052611c0e6040600020611b7283825414613eb3565b611bff600a6004830192611b92611b8d610c80865460ff1690565b61424c565b611ba160058201544210613eff565b6006810154611bcb90611bc4906001600160a01b03165b6001600160a01b031690565b331461428b565b0154611bf8611bda82336128ec565b916001600160d01b0390611bf1906112e0906129a6565b169161402a565b10156142c8565b805461ff001916610100179055565b604051948594019084614320565b34610a8a576040366003190112610a8a57610bee600435611c3c81610bb3565b60243590336129fd565b9181601f84011215610a8a578235916001600160401b038311610a8a576020808501948460051b010111610a8a57565b34610a8a576060366003190112610a8a576001600160401b03600435602435828111610a8a57611caa903690600401611c46565b92604435908111610a8a5783611cc584923690600401611c46565b611ccd614007565b611ce184600052601b602052604060002090565b90611cee85835414613eb3565b6004820192611d09611d04610c80865460ff1690565b61434e565b60185494611d1d60088501548714156143aa565b611d2f611d2a8786615694565b614406565b611d3a838214614449565b611dc4876007860197611dbc600a611d518b610919565b6020815191012098015497611dae896040519485936020850197889094939260809260a08301967f45de75acfcd4cbcc5691559486749bf0d5eb65e4b24c59ac2f258ba6bfceaa3484526020840152604083015260608201520152565b03601f1981018352826106b7565b519020612edb565b9760009889945b838610611e8c575050507fda7dba8f94d70cde423cce3a243bebf95d2ec927507b566f67e329dcfe2d06bb877fbadbd87941bb6424ed4aa4719bf01a3319b64480e49f89018c718603239553d2611e6589611e4c8a610cca8f611e45611e3e8e6112e56112e060018060d01b03926129a6565b6064900490565b11156145a8565b611e58610ce582610919565b60405191829185836141aa565b0390a1601854604080519283526020830191909152819081015b0390a161161f6001600b55565b909192939499868b611ec8611bb8611ec3611ebb611eb5611eae868a8f614486565b3691611075565b896145f4565b938a8a6144c7565b6144d7565b6001600160a01b03821690611ede9082146144e1565b8d88886000925b8310611f21575050505091611f00611f1192611f17946128ec565b90611f0c82151561455c565b61316a565b9a6135c6565b9493929190611dcb565b8394955092611f3d611bb8611ec385611f4495611f49986144c7565b141561451d565b6135c6565b90899291888f8990611ee5565b6064359060ff82168203610a8a57565b6084359060ff82168203610a8a57565b34610a8a5760c0366003190112610a8a57600435611f9381610bb3565b60443590602435611fa2611f56565b83421161202a5761201e61161f94612025926040519060208201927fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf845260018060a01b038816604084015286606084015260808301526080825261200682610681565b61201960a4359360843593519020612edb565b612c6c565b9182612c16565b615bc7565b604051632341d78760e11b815260048101859052602490fd5b6001600160401b0381116106615760051b60200190565b81601f82011215610a8a5780359161207183612043565b9261207f60405194856106b7565b808452602092838086019260051b820101928311610a8a578301905b8282106120a9575050505090565b8135815290830190830161209b565b34610a8a5760c0366003190112610a8a576001600160401b03600435818111610a8a576120e99036906004016110ac565b90604435818111610a8a5736602382011215610a8a57612113903690602481600401359101611075565b608435918211610a8a57610a86926121326111ed93369060040161205a565b916064359160243590613539565b34610a8a576020366003190112610a8a57600435601c54811015610a8a57602090601c6000527f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a2110154604051908152f35b34610a8a576080366003190112610a8a576004356001600160401b038111610a8a576121c46111b49136906004016110ac565b604435612241606435916121e861112f61112885600052601d602052604060002090565b61220761220261112883600052601a602052604060002090565b6152f6565b33600090815260208190526040902061221f9061117e565b604051633972e9fb60e21b602082015260248101919091529384906044820190565b601e549261224e84612f29565b9360005b81811061226c57610a866111ed338887876024358b613cc4565b8061121761120d61227c93611405565b612252565b34610a8a576040366003190112610a8a576004356024358015158103610a8a577f78975aaf742630489badd22949b88ac50eaaea576339ee05440b671a33bfb6a9916122cb614007565b611e7f6122e282600052601b602052604060002090565b6122ee83825414613eb3565b6122fd60058201544210613eff565b612311610c84610c80600484015460ff1690565b600b81019061234061233b610c8061112833869060018060a01b0316600052602052604060002090565b613f86565b612351601854600883015414613fc2565b612379610cca612365600a840154336128ec565b336000908152602095909552604090942090565b84156123b95760020161238d82825461316a565b90555b604080519384523360208501529315159383019390935260608201929092529081906080820190565b6003016123c782825461316a565b9055612390565b34610a8a5760e0366003190112610a8a576004356123eb81610bb3565b6024356123f781610bb3565b60443590606435612406611f66565b8142116124f1576001600160a01b0385811660008181526007602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99281019283529283019390935292861660608201526080810187905260a081019190915260c0808201949094529283526124aa92909161249760e0836106b7565b61201960c4359360a43593519020612edb565b6001600160a01b03848116908216036124c7575061161f92612b0f565b6040516325c0072360e11b81526001600160a01b0391821660048201529084166024820152604490fd5b60405163313c898160e11b815260048101839052602490fd5b97949161252f90610aa09c9a97949b9895928a526101608060208c01528a0190610957565b604089019a909a52606088015215156080870152151560a086015260c08501526001600160a01b031660e084015261010083015261012082015280830361014090910152611486565b34610a8a576020366003190112610a8a5760043580600052601b60205260406000206125a78154928314613eb3565b610a86600282015492600383015490600484015460058501546125d3600687015460018060a01b031690565b90600887015492600a880154946125f860096125f160018c01610919565b9a016154dd565b966040519a8b9a60ff808660081c169516938c61250a565b34610a8a576040366003190112610a8a57602061266a60043561263281610bb3565b6024359061263f82610bb3565b60018060a01b03166000526001835260406000209060018060a01b0316600052602052604060002090565b54604051908152f35b34610a8a576020366003190112610a8a576020611561600435614637565b34610a8a576000366003190112610a8a576020601e54604051908152f35b34610a8a576040366003190112610a8a576004356126cc81610bb3565b6024359063ffffffff82168203610a8a57610a869161271c916126ed612bfd565b506126f6612bfd565b506001600160a01b03166000908152600960205260409020612716612bfd565b5061142f565b506040519061272a82610666565b5465ffffffffffff811680835260309190911c60209283019081526040805192835290516001600160d01b031692820192909252918291820190565b9794999895926127ab9061279d6127b99461278f6101009b98958d610120908181520190610957565b8c810360208e015290610957565b908a820360408c0152610957565b9088820360608a0152610957565b97608087015260a086015260c085015260e08401521515910152565b34610a8a57600080600319360112610b8157604051908181600c546127f9816103e3565b808452936001918083169081156128c8575060011461287d575b5050612821925003826106b7565b604051906128328261092d8161041d565b610a8660405161284c81612845816104af565b03826106b7565b60405161285c8161284581610524565b601054601154601354916014549360ff6015541695604051998a998a612766565b9150600c8252600080516020615c988339815191525b8483106128ad575061282193505081016020013880612813565b81935090816020925483858901015201910190918492612893565b9150506020925061282194915060ff191682840152151560051b8201013880612813565b6001600160a01b03166000908152600960205260408120909161290e906129a6565b81549083829160058411612957575b61292893508461343e565b8061293c5750505b6001600160d01b031690565b9161294960209293613140565b92815220015460301c612930565b91926129628161329b565b8103908111611327576129289385875265ffffffffffff808360208a200154169085161060001461299457509161291d565b9291506129a09061315c565b9061291d565b65ffffffffffff6129b64361310e565b16808210156129c95750610aa09061310e565b6044925060405191637669fc0f60e11b835260048301526024820152fd5b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0380821694939291908515612af65782168015612add576001600160a01b03821660009081526020819052604090205495848710612aae5784610713969703612a5f8460018060a01b03166000526000602052604060002090565b556001600160a01b0384166000908152602081815260409182902080548801905590518681527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a36156df565b60405163391434e360e21b81526001600160a01b03841660048201526024810188905260448101869052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b6001600160a01b038082169291908315612baa578216938415612b915780612b877f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92594612b7060209560018060a01b03166000526001602052604060002090565b9060018060a01b0316600052602052604060002090565b55604051908152a3565b604051634a1406b160e11b815260006004820152602490fd5b60405163e602df0560e01b815260006004820152602490fd5b906001600160a01b0380831615612baa57811615612b9157612b70612bfa9260018060a01b03166000526001602052604060002090565b55565b60405190612c0a82610666565b60006020838281520152565b6001600160a01b03811660009081526007602052604090208054600181019091559091819003612c44575050565b6040516301d4b62360e61b81526001600160a01b039092166004830152602482015260449150fd5b91610aa09391612c7b93612c84565b90929192612d34565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612d0857926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612cfc5780516001600160a01b03811615612cf357918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b60041115612d1e57565b634e487b7160e01b600052602160045260246000fd5b612d3d81612d14565b80612d46575050565b612d4f81612d14565b60018103612d695760405163f645eedf60e01b8152600490fd5b612d7281612d14565b60028103612d935760405163fce698f760e01b815260048101839052602490fd5b80612d9f600392612d14565b14612da75750565b6040516335e2f38360e21b81526004810191909152602490fd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480612eb2575b15612e1c577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a08152612eac8161069c565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614612df3565b604290612ee6612dc1565b906040519161190160f01b8352600283015260228201522090565b604051602081018181106001600160401b038211176106615760405260008152906000368137565b90612f3382612043565b612f4060405191826106b7565b8281528092612f51601f1991612043565b0190602036910137565b60ff8114612f995760ff811690601f8211612f875760405191612f7d83610666565b8252602082015290565b604051632cd44ac360e21b8152600490fd5b50604051600554816000612fac836103e3565b808352926001908181169081156130325750600114612fd3575b50610aa0925003826106b7565b6005600090815291507f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8483106130175750610aa0935050810160200138612fc6565b81935090816020925483858901015201910190918492612ffe565b905060209250610aa094915060ff191682840152151560051b82010138612fc6565b60ff81146130765760ff811690601f8211612f875760405191612f7d83610666565b50604051600654816000613089836103e3565b8083529260019081811690811561303257506001146130af5750610aa0925003826106b7565b6006600090815291507ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8483106130f35750610aa0935050810160200138612fc6565b819350908160209254838589010152019101909184926130da565b65ffffffffffff90818111613121571690565b604490604051906306dfcc6560e41b8252603060048301526024820152fd5b60001981019190821161132757565b9190820391821161132757565b906001820180921161132757565b9190820180921161132757565b600a805460008160058111613225575b509290925b8381106131cb57505060009180156000146131a957505050600090565b6131b290613140565b9152600080516020615cd8833981519152015460301c90565b90928082169080831860011c8201809211611327578360005265ffffffffffff8083600080516020615cd8833981519152015416908616106000146132135750925b9061318c565b93915061321f9061315c565b9061320d565b90916132308261329b565b82039182116113275783835265ffffffffffff8083600080516020615cd88339815191520154169086161060001461326b5750905b38613187565b91506132769061315c565b613265565b8115613285570490565b634e487b7160e01b600052601260045260246000fd5b6001811115610aa057600181600160801b8110156133b4575b61335c61335261334861333e61333461332a61336897600488600160401b6133639a10156133a7575b64010000000081101561339a575b6201000081101561338d575b610100811015613381575b6010811015613375575b101561336d575b60030260011c613323818b61327b565b0160011c90565b613323818a61327b565b613323818961327b565b613323818861327b565b613323818761327b565b613323818661327b565b809361327b565b821190565b900390565b60011b613313565b811c9160021b9161330c565b60081c91811b91613302565b60101c9160081b916132f7565b60201c9160101b916132eb565b60401c9160201b916132dd565b50600160401b9050608082901c6132b4565b600a54600090806133d8575050600090565b8060001981011161132757600a7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a79252015460301c90565b80546000918161342257505050600090565b6000199282848101116113275760209181522001015460301c90565b91905b83821061344e5750505090565b9091928083169080841860011c82018092116113275760008581526020902082015465ffffffffffff908116908416101561348d5750925b9190613441565b9392506134999061315c565b91613486565b156134a657565b60405162461bcd60e51b815260206004820152602360248201527f4d75737420686f6c6420746f6b656e7320746f206372656174652070726f706f6044820152621cd85b60ea1b6064820152608490fd5b156134fe57565b60405162461bcd60e51b815260206004820152601360248201527210da185a5b881b9bdd081cdd5c1c1bdc9d1959606a1b6044820152606490fd5b92909391336000526000602052613556604060002054151561349f565b841561358157610aa09482600052601d60205261357a60ff604060002054166134f7565b3394613cc4565b60405162461bcd60e51b815260206004820152601960248201527f4475726174696f6e206d75737420626520706f736974697665000000000000006044820152606490fd5b60001981146113275760010190565b8181106135e0575050565b600081556001016135d5565b90601f82116135f9575050565b61071391600c600052600080516020615c98833981519152906020601f840160051c83019310613631575b601f0160051c01906135d5565b9091508190613624565b90601f8211613648575050565b61071391600d600052600080516020615cf8833981519152906020601f840160051c8301931061363157601f0160051c01906135d5565b90601f821161368c575050565b61071391600e600052600080516020615cb8833981519152906020601f840160051c8301931061363157601f0160051c01906135d5565b90601f82116136d0575050565b61071391600f600052600080516020615d38833981519152906020601f840160051c8301931061363157601f0160051c01906135d5565b9190601f811161371657505050565b610713926000526020600020906020601f840160051c8301931061363157601f0160051c01906135d5565b9081516001600160401b0381116106615761376681613761600c546103e3565b6135ec565b602080601f83116001146137a25750819293600092613797575b50508160011b916000199060031b1c191617600c55565b015190503880613780565b90601f198316946137c3600c600052600080516020615c9883398151915290565b926000905b8782106138005750508360019596106137e7575b505050811b01600c55565b015160001960f88460031b161c191690553880806137dc565b806001859682949686015181550195019301906137c8565b9081516001600160401b0381116106615761383d81613838600d546103e3565b61363b565b602080601f8311600114613879575081929360009261386e575b50508160011b916000199060031b1c191617600d55565b015190503880613857565b90601f1983169461389a600d600052600080516020615cf883398151915290565b926000905b8782106138d75750508360019596106138be575b505050811b01600d55565b015160001960f88460031b161c191690553880806138b3565b8060018596829496860151815501950193019061389f565b9081516001600160401b038111610661576139148161390f600e546103e3565b61367f565b602080601f83116001146139505750819293600092613945575b50508160011b916000199060031b1c191617600e55565b01519050388061392e565b90601f19831694613971600e600052600080516020615cb883398151915290565b926000905b8782106139ae575050836001959610613995575b505050811b01600e55565b015160001960f88460031b161c1916905538808061398a565b80600185968294968601518155019501930190613976565b9081516001600160401b038111610661576139eb816139e6600f546103e3565b6136c3565b602080601f8311600114613a275750819293600092613a1c575b50508160011b916000199060031b1c191617600f55565b015190503880613a05565b90601f19831694613a48600f600052600080516020615d3883398151915290565b926000905b878210613a85575050836001959610613a6c575b505050811b01600f55565b015160001960f88460031b161c19169055388080613a61565b80600185968294968601518155019501930190613a4d565b91909182516001600160401b03811161066157613ac481613abe84546103e3565b84613707565b602080601f8311600114613b00575081929394600092613af5575b50508160011b916000199060031b1c1916179055565b015190503880613adf565b90601f19831695613b1685600052602060002090565b926000905b888210613b5357505083600195969710613b3a575b505050811b019055565b015160001960f88460031b161c19169055388080613b30565b80600185968294968601518155019501930190613b1b565b805182101561142a5760209160051b010190565b15613b8657565b60405162461bcd60e51b815260206004820152601a60248201527f54617267657420636861696e206e6f7420737570706f727465640000000000006044820152606490fd5b601c54600160401b811015610661576001810180601c5581101561142a57601c6000527f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a2110155565b601e54600160401b811015610661576001810180601e5581101561142a57601e600052600080516020615d188339815191520155565b90815491600160401b8310156106615782613c6c9160016107139501815561142f565b90919082549060031b91821b91600019901b1916179055565b9081526001600160a01b039091166020820152606060408201819052610aa092910190610957565b604090610aa0939281528160208201520190611486565b91949060175495613cdc613cd7886135c6565b601755565b613d59613cf388600052601b602052604060002090565b91888355613d2e600194613d0988878701613a9d565b6000600286015560006003860155613d286004860160ff198154169055565b4261316a565b60058401556006830180546001600160a01b0319166001600160a01b03871617905560078301613a9d565b846008820155613d76613d6b4361310e565b65ffffffffffff1690565b80613ea25750819060005b600a820155600960009101925b613e4d575b505050613e37613e47937f7585f467599d0f008985f231af99293be388626ac16ca59505c2f8f88969cd637f5d1231ca3a274bcd2f510e0d53a889213ebf0315b86ee6bb9d73da08fba7460696947fdb17271edb72bcaba16ce918d885db2e701491c9ff3f713f80caf9d614aa9ff494613e0c8a613bcb565b613e1c6040519283928c84613c85565b0390a160408051888152602081019290925290918291820190565b0390a16040519182918583613cad565b0390a190565b8651811015613e9d5780613e83613e7e611128613e6d613e97958c613b6b565b51600052601d602052604060002090565b613b7f565b611f44613e90828a613b6b565b5185613c49565b81613d8e565b613d93565b613eab90613140565b908291613d81565b15613eba57565b60405162461bcd60e51b815260206004820152601760248201527f50726f706f73616c20646f6573206e6f742065786973740000000000000000006044820152606490fd5b15613f0657565b60405162461bcd60e51b815260206004820152600c60248201526b159bdd1a5b99c8195b99195960a21b6044820152606490fd5b15613f4157565b60405162461bcd60e51b815260206004820152601960248201527f50726f706f73616c20616c7265616479206578656375746564000000000000006044820152606490fd5b15613f8d57565b60405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e481d9bdd1959609a1b6044820152606490fd5b15613fc957565b60405162461bcd60e51b815260206004820152601660248201527557726f6e6720636861696e20666f7220766f74696e6760501b6044820152606490fd5b6002600b5414614018576002600b55565b604051633ee5aeb560e01b8152600490fd5b90600a820291808304600a149015171561132757565b8181029291811591840414171561132757565b9081600052601b60205261406e604060002092835414613eb3565b60028201546003830154928382019081831161132757600a01546064906140a5906001600160d01b03906112e5906112e0906129a6565b041115928391826140b7575b50509190565b11905038806140b1565b156140c857565b606460405162461bcd60e51b815260206004820152602060248201527f45786563757465206f6e6c7920696e20676f7665726e616e636520636861696e6044820152fd5b1561411357565b60405162461bcd60e51b815260206004820152602760248201527f566f74696e67206e6f7420656e64656420616e642071756f72756d206e6f74206044820152661c995858da195960ca1b6064820152608490fd5b1561416f57565b60405162461bcd60e51b8152602060048201526013602482015272141c9bdc1bdcd85b081b9bdd081c185cdcd959606a1b6044820152606490fd5b9190825260209160408382015260009282546141c5816103e3565b93846040850152600191828116908160001461422757506001146141ec575b505050505090565b6000908152828120949550935b8585106142135750505060609250010138808080806141e4565b8054858501606001529382019381016141f9565b93505050506060935060ff929192191683830152151560051b010138808080806141e4565b1561425357565b60405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e48195e1958dd5d195960821b6044820152606490fd5b1561429257565b60405162461bcd60e51b815260206004820152600e60248201526d27b7363c9034b734ba34b0ba37b960911b6044820152606490fd5b156142cf57565b60405162461bcd60e51b815260206004820152602360248201527f496e73756666696369656e7420766f74696e6720706f77657220746f2063616e60448201526218d95b60ea1b6064820152608490fd5b91926060938192845260406020850152816040850152848401376000828201840152601f01601f1916010190565b1561435557565b60405162461bcd60e51b815260206004820152602760248201527f50726f706f73616c20616c726561647920657865637574656420696e20746869604482015266399031b430b4b760c91b6064820152608490fd5b156143b157565b60405162461bcd60e51b815260206004820152602760248201527f557365206578656375746550726f706f73616c20696e20676f7665726e616e63604482015266329031b430b4b760c91b6064820152608490fd5b1561440d57565b60405162461bcd60e51b8152602060048201526014602482015273436861696e206e6f7420696e207461726765747360601b6044820152606490fd5b1561445057565b60405162461bcd60e51b815260206004820152600e60248201526d426164207369676e61747572657360901b6044820152606490fd5b919081101561142a5760051b81013590601e1981360301821215610a8a5701908135916001600160401b038311610a8a576020018236038113610a8a579190565b919081101561142a5760051b0190565b35610aa081610bb3565b156144e857565b60405162461bcd60e51b815260206004820152600d60248201526c426164207369676e617475726560981b6044820152606490fd5b1561452457565b60405162461bcd60e51b815260206004820152601060248201526f223ab83634b1b0ba329039b4b3b732b960811b6044820152606490fd5b1561456357565b60405162461bcd60e51b815260206004820152601b60248201527f4e6f20766f74696e6720706f77657220617420736e617073686f7400000000006044820152606490fd5b156145af57565b60405162461bcd60e51b815260206004820152601a60248201527f51756f72756d206e6f74207265616368656420627920736967730000000000006044820152606490fd5b8151610aa092612c7b92604019830161462c5761462592506020820151906060604084015193015160001a90612c84565b9192909190565b505060009160029190565b614650600091808352601b602052604083205414613eb3565b80601e54915b82811061466557505050600190565b6146856146718261469e565b600052601d60205260ff6040600020541690565b1561469857614693906135c6565b614656565b50905090565b601e548110156146c157601e600052600080516020615d18833981519152015490565b60405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840c6d0c2d2dc40d2dcc8caf606b1b6044820152606490fd5b909291926147098161105a565b9161471760405193846106b7565b829482845282820111610a8a576020610713930190610934565b9190604083820312610a8a5782516001600160e01b031981168103610a8a57926020810151906001600160401b038211610a8a57019080601f83011215610a8a578151610aa0926020016146fc565b90816020910312610a8a575190565b9190826040910312610a8a5760208251920151610aa081610bb3565b9080601f83011215610a8a578151610aa0926020016146fc565b9080601f83011215610a8a578151906147dd82612043565b926147eb60405194856106b7565b828452602092838086019160051b83010192808411610a8a57848301915b8483106148195750505050505090565b82516001600160401b038111610a8a57869161483a848480948901016147ab565b815201920191614809565b91909161010081840312610a8a578051916001600160401b0392838111610a8a57846148729184016147ab565b936020830151848111610a8a578161488b9185016147ab565b936040840151818111610a8a57826148a49186016147ab565b936060810151828111610a8a57836148bd9183016147ab565b9360808201519360a08301519360c0840151908111610a8a5760e0916148e49185016147c5565b92015190565b6148fe602091828082518301019101614731565b91906001600160e01b031916630236fce560e51b810361493d5750818161492e9261071394518301019101614845565b9695909594919493929361503f565b63f0f9e6b760e01b8103614966575081816149619261071394518301019101614780565b61513d565b632ab43f7f60e11b810361498f5750818161498a9261071394518301019101614780565b6151dd565b6304fa45bf60e31b81036149c2575081816149b3926107139451830101910161478f565b6001600160a01b03169061533a565b633972e9fb60e21b81036149eb575081816149e69261071394518301019101614780565b6153ea565b63093f734560e31b8103614a1457508181614a0f9261071394518301019101614780565b614a87565b633e78500160e21b8103614a3d57508181614a389261071394518301019101614780565b614c22565b633cdb568760e11b14915061071390505760405162461bcd60e51b81526020600482015260116024820152702ab735b737bbb71037b832b930ba34b7b760791b6044820152606490fd5b80600052601d60205260ff60406000205416614b35576018548114614af057614aeb81614ae2610cca7fbba9d55e9fd1a441b1617724e2fdb76777d15ec77ab2b72ac15952cbe97085db94600052601d602052604060002090565b6111ed81613c13565b0390a1565b60405162461bcd60e51b815260206004820152601860248201527f43616e6e6f74206164642063757272656e7420636861696e00000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601760248201527f436861696e20616c726561647920737570706f727465640000000000000000006044820152606490fd5b15614b8157565b60405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f742072656d6f76652063757272656e7420636861696e00000000006044820152606490fd5b601e548015614c0c576000198101908082101561142a577f50bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e34f600091601e83520155601e55565b634e487b7160e01b600052603160045260246000fd5b614c4260ff614c3b83600052601d602052604060002090565b54166134f7565b614c50601854821415614b7a565b614c71614c6782600052601d602052604060002090565b805460ff19169055565b60005b601e5480821015614cee5782614c8c61120d84611405565b14614ca05750614c9b906135c6565b614c74565b91614ce6614aeb92613c6c614ce061120d614cdb7f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d598613140565b611405565b91611405565b6111ed614bc6565b5050614aeb7f11a9d1a77f76361ed131c19b1dc5758504c51dbde2e49fc973a0ef9577ad13d5916111ed565b15614d2157565b60405162461bcd60e51b815260206004820152601660248201527553796d626f6c2063616e6e6f7420626520656d70747960501b6044820152606490fd5b15614d6657565b60405162461bcd60e51b815260206004820152601860248201527f4c6f636174696f6e2063616e6e6f7420626520656d70747900000000000000006044820152606490fd5b15614db257565b60405162461bcd60e51b815260206004820152601460248201527324b73b30b634b210353ab934b9b234b1ba34b7b760611b6044820152606490fd5b15614df557565b60405162461bcd60e51b815260206004820152600d60248201526c496e76616c6964204f4b544d4f60981b6044820152606490fd5b15614e3157565b60405162461bcd60e51b815260206004820152600b60248201526a0496e76616c6964204b50560ac1b6044820152606490fd5b805190600160401b82116106615760125482601255808310614edc575b5060126000526020908101907fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34446000925b848410614ec0575050505050565b60018382614ed083945186613a9d565b01920193019290614eb2565b600060128152837fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344492830192015b828110614f18575050614e81565b80614f25600192546103e3565b80614f32575b5001614f0a565b601f908181118414614f4a5750508281555b38614f2b565b83614f6c92614f5e85600052602060002090565b920160051c820191016135d5565b60008181526020812081835555614f44565b989796949592614fc190614fb3614fa3614fcf9597948d610100908181520190610957565b6020978d89818403910152610957565b908b820360408d0152610957565b9089820360608b0152610957565b93608088015260a087015285830360c08701528151908184528084019381808460051b8301019401946000915b84831061501157505050505060e09150930152565b9091929394848061502e600193601f198682030187528a51610957565b980193019301919594939290614ffc565b9490959193969296855115615101577f62d6efdb8dbca656ac38d327c1d66a4ccaeabc91c464fe5e7352b604858f5f4697614aeb9561508089511515614d1a565b61508c81511515614d5f565b615097831515614dab565b6150a2841515614dee565b6150ad861515614e2a565b6150b688613741565b6150bf89613818565b6150c8816138ef565b6150d1826139c6565b6150da83601055565b6150e384601155565b6150ec85614e64565b6150f586601355565b60405198899889614f7e565b60405162461bcd60e51b81526020600482015260146024820152734e616d652063616e6e6f7420626520656d70747960601b6044820152606490fd5b801515806151d2575b1561518d5760168054908290556040805191825260208201929092527fd0198ea88bf9c4ad5317b68e697944e524541fcb494d854f095b1cd88a097ab69181908101614aeb565b60405162461bcd60e51b815260206004820152601960248201527f496e76616c69642071756f72756d2070657263656e74616765000000000000006044820152606490fd5b506064811115615146565b80600052601d6020526151f760ff604060002054166134f7565b601854908181146152425760188190556040805192835260208301919091527f979103c7afbf0138fe781172504ceb318ff78f9a420de8cabac8141f0121b521919081908101614aeb565b60405162461bcd60e51b815260206004820152600d60248201526c14d85b594818da185a5b881251609a1b6044820152606490fd5b1561527e57565b60405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606490fd5b156152b957565b60405162461bcd60e51b81526020600482015260156024820152744d6f64756c6520616c72656164792065786973747360581b6044820152606490fd5b156152fd57565b60405162461bcd60e51b8152602060048201526015602482015274135bd91d5b1948191bd95cc81b9bdd08195e1a5cdd605a1b6044820152606490fd5b7ff14475b19484bf096265507cc0c41cd3bf1994992088806830686e2d7272271991906153716001600160a01b0383161515615277565b80600052601a60205261538c60ff60406000205416156152b2565b600081815260196020526040902080546001600160a01b0319166001600160a01b038416179055601a602090815260406000819020805460ff1916600117905580519283526001600160a01b03909316908201529081908101614aeb565b60207f4c7c76abe482a2c36ea52f1b999474c69f8b4afeeac5635f8aea2526864ba8539180600052601a825261542760ff604060002054166152f6565b600081815260198352604080822080546001600160a01b0319169055601a845290819020805460ff1916905551908152a1565b6012549061546782612043565b916040615476815194856106b7565b8184528360208091019160126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444906000935b8585106154ba57505050505050565b600184819284516154cf81612845818a610599565b8152019301940193916154ab565b9060405191828154918282526020928383019160005283600020936000905b82821061551257505050610713925003836106b7565b8554845260019586019588955093810193909101906154fc565b601c90815492838210156155c557810191828211611327578383116155bd575b8183038381116113275761555f90612f29565b93825b84811061557157505050505090565b8181101561142a576155b89083600052807f0e4562a10381dec21b205ed72637e6b1b523bdd0e4d4d50af5cd23dd4500a21101546112216155b2878461314f565b89613b6b565b615562565b83925061554c565b50505050610aa0612f01565b6155e581600052601b602052604060002090565b6155f182825414613eb3565b600481015460ff8160081c1661568c5760ff1661568557615613600592614053565b9290910154421091821592828061567e575b6156755782918261565c575b5050615655578161564c575b5061564757600090565b600290565b9050153861563d565b5050600190565b8492509061566d575b503880615631565b905038615665565b50505050600590565b5081615625565b5050600390565b505050600490565b9060005b6009830180548210156156d6576156b082849261142f565b90549060031b1c146156ce576156c76009916135c6565b9050615698565b505050600190565b50505050600090565b6001600160a01b0390811692918190841561576b575b16908115615723575b61071393600052600860205280604060002054169160005260406000205416906157b0565b61572c83615938565b936157364361310e565b6001600160d01b039586806157496133c6565b1691169003958611611327576107139561576291615a22565b505093506156fe565b905061577683615938565b906157804361310e565b6001600160d01b039283806157936133c6565b169116019283116113275783926157a991615a22565b50506156f5565b6001600160a01b038083169392919081169081851415806158f9575b6157d8575b5050505050565b8161585d575b5050826157ed575b80806157d1565b6001600160a01b031660009081526009602052604090207fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7249161583a916158349091615938565b90615902565b604080516001600160d01b039384168152919092166020820152a23880806157e6565b6001600160a01b0316600090815260096020526040902061587d84615938565b6158864361310e565b6001600160d01b0391828061589a86613410565b169116900392828411611327577fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724936158ef926158d692615b0b565b6040805192851683529316602082015291829190820190565b0390a238806157de565b508315156157cc565b9061590c4361310e565b6001600160d01b0391828061592086613410565b169116019182116113275761593492615b0b565b9091565b6001600160d01b039081811161594c571690565b604490604051906306dfcc6560e41b825260d060048301526024820152fd5b600a5490600160401b821015610661576001820180600a5582101561142a57600a600052805160209091015160301b65ffffffffffff191665ffffffffffff9190911617600080516020615cd883398151915290910155565b8054600160401b811015610661576159e19160018201815561142f565b615a0c57815160209092015160301b65ffffffffffff191665ffffffffffff92909216919091179055565b634e487b7160e01b600052600060045260246000fd5b600a549192918015615ae157615a3a615a5291613140565b600a600052600080516020615cd88339815191520190565b9081549165ffffffffffff90818416918316808311615acf57869203615a9757615a9092509065ffffffffffff82549181199060301b169116179055565b60301c9190565b5050615aca90615ab6615aa861104d565b65ffffffffffff9092168252565b6001600160d01b038516602082015261596b565b615a90565b604051632520601d60e01b8152600490fd5b50615b0590615af1615aa861104d565b6001600160d01b038416602082015261596b565b60009190565b80549293928015615ba257615b22615b2f91613140565b8260005260206000200190565b9182549265ffffffffffff91828516928116808411615acf57879303615b6e5750615a9092509065ffffffffffff82549181199060301b169116179055565b915050615aca91615b8e615b8061104d565b65ffffffffffff9093168352565b6001600160d01b03861660208301526159c4565b5090615b0591615bb3615b8061104d565b6001600160d01b03851660208301526159c4565b6001600160a01b03808316929181811690848203615c5c57600082815260086020526040902080546001600160a01b031981166001600160a01b038716179091556107139593169392615c569285907f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f600080a46001600160a01b031660009081526020819052604090205490565b916157b0565b60405162461bcd60e51b815260206004820152601360248201527211195b1959d85d1a5bdb88191a5cd8589b1959606a1b6044820152606490fdfedf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7bb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fdc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8d7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb550bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e3508d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802a26469706673582212205eddae3f70083f1206f843d74c1dd42c83bc9cd2672ae776335ecdaef553d72464736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/backend/cache/solidity-files-cache.json b/backend/cache/solidity-files-cache.json index 7c07c93..8e10d2f 100644 --- a/backend/cache/solidity-files-cache.json +++ b/backend/cache/solidity-files-cache.json @@ -1,9 +1,9 @@ { "_format": "hh-sol-cache-2", "files": { - "/home/alex/Digital_Legal_Entity(DLE)/backend/contracts/DLE.sol": { - "lastModificationDate": 1754682456067, - "contentHash": "6d46f24614a8d6c838144dcfad200e26", + "/app/contracts/DLE.sol": { + "lastModificationDate": 1755001745034, + "contentHash": "a77cbe367dec496f574716fd50e1ef07", "sourceName": "contracts/DLE.sol", "solcConfig": { "version": "0.8.20", @@ -44,7 +44,44 @@ "DLE" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "/app/node_modules/@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "lastModificationDate": 1754306760451, + "contentHash": "190613e556d509d9e9a0ea43dc5d891d", + "sourceName": "@openzeppelin/contracts/utils/ReentrancyGuard.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "ReentrancyGuard" + ] + }, + "/app/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { "lastModificationDate": 1754306764456, "contentHash": "227a6eb2225701c12d9c959b758b6333", "sourceName": "@openzeppelin/contracts/token/ERC20/ERC20.sol", @@ -86,160 +123,10 @@ "ERC20" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/ReentrancyGuard.sol": { - "lastModificationDate": 1754306760451, - "contentHash": "190613e556d509d9e9a0ea43dc5d891d", - "sourceName": "@openzeppelin/contracts/utils/ReentrancyGuard.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "ReentrancyGuard" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/Context.sol": { - "lastModificationDate": 1754306760451, - "contentHash": "67bfbc07588eb8683b3fd8f6f909563e", - "sourceName": "@openzeppelin/contracts/utils/Context.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "Context" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/draft-IERC6093.sol": { - "lastModificationDate": 1754306760460, - "contentHash": "267d92fe4de67b1bdb3302c08f387dbf", - "sourceName": "@openzeppelin/contracts/interfaces/draft-IERC6093.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "IERC1155Errors", - "IERC20Errors", - "IERC721Errors" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "lastModificationDate": 1754306764456, - "contentHash": "8f19f64d2adadf448840908bbaf431c8", - "sourceName": "@openzeppelin/contracts/token/ERC20/IERC20.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "IERC20" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "/app/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol": { "lastModificationDate": 1754306768254, - "contentHash": "794db3115001aa372c79326fcfd44b1f", - "sourceName": "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol", + "contentHash": "51c2083b160453420aaa0a046c16d5ca", + "sourceName": "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol", "solcConfig": { "version": "0.8.20", "settings": { @@ -266,92 +153,18 @@ } }, "imports": [ - "../IERC20.sol" + "../ERC20.sol", + "../../../governance/utils/Votes.sol", + "../../../utils/structs/Checkpoints.sol" ], "versionPragmas": [ "^0.8.20" ], "artifacts": [ - "IERC20Metadata" + "ERC20Votes" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { - "lastModificationDate": 1754306764465, - "contentHash": "d57b0dba03e8cc7942bf797fc9fe1d29", - "sourceName": "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "./Hashes.sol" - ], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "MerkleProof" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/cryptography/Hashes.sol": { - "lastModificationDate": 1754306764456, - "contentHash": "34f1345e1a955860b49b83bf791500a6", - "sourceName": "@openzeppelin/contracts/utils/cryptography/Hashes.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "Hashes" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol": { + "/app/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol": { "lastModificationDate": 1754306768254, "contentHash": "b1a8fc63b83ce00408e0c9ed1230b717", "sourceName": "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol", @@ -394,7 +207,7 @@ "ERC20Permit" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "/app/node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { "lastModificationDate": 1754306764456, "contentHash": "81de029d56aa803972be03c5d277cb6c", "sourceName": "@openzeppelin/contracts/utils/cryptography/ECDSA.sol", @@ -431,51 +244,10 @@ "ECDSA" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol": { - "lastModificationDate": 1754306768254, - "contentHash": "51c2083b160453420aaa0a046c16d5ca", - "sourceName": "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "../ERC20.sol", - "../../../governance/utils/Votes.sol", - "../../../utils/structs/Checkpoints.sol" - ], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "ERC20Votes" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/Nonces.sol": { + "/app/node_modules/@openzeppelin/contracts/utils/Context.sol": { "lastModificationDate": 1754306760451, - "contentHash": "c32d108058718efb9061b88e83a83f79", - "sourceName": "@openzeppelin/contracts/utils/Nonces.sol", + "contentHash": "67bfbc07588eb8683b3fd8f6f909563e", + "sourceName": "@openzeppelin/contracts/utils/Context.sol", "solcConfig": { "version": "0.8.20", "settings": { @@ -506,91 +278,13 @@ "^0.8.20" ], "artifacts": [ - "Nonces" + "Context" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/cryptography/EIP712.sol": { - "lastModificationDate": 1754306764456, - "contentHash": "8dbb261c55f358342798c4d1803d4f8e", - "sourceName": "@openzeppelin/contracts/utils/cryptography/EIP712.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "./MessageHashUtils.sol", - "../ShortStrings.sol", - "../../interfaces/IERC5267.sol" - ], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "EIP712" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { - "lastModificationDate": 1754306768254, - "contentHash": "94ec15baf0d5df863f45b8f351937ec7", - "sourceName": "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "IERC20Permit" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC5267.sol": { + "/app/node_modules/@openzeppelin/contracts/interfaces/draft-IERC6093.sol": { "lastModificationDate": 1754306760460, - "contentHash": "94364524cb1a39dcbc3d3afff6d8e53e", - "sourceName": "@openzeppelin/contracts/interfaces/IERC5267.sol", + "contentHash": "267d92fe4de67b1bdb3302c08f387dbf", + "sourceName": "@openzeppelin/contracts/interfaces/draft-IERC6093.sol", "solcConfig": { "version": "0.8.20", "settings": { @@ -621,209 +315,15 @@ "^0.8.20" ], "artifacts": [ - "IERC5267" + "IERC1155Errors", + "IERC20Errors", + "IERC721Errors" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/ShortStrings.sol": { - "lastModificationDate": 1754306760451, - "contentHash": "94e7feaf138d08fb736e43ca0be9bf26", - "sourceName": "@openzeppelin/contracts/utils/ShortStrings.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "./StorageSlot.sol" - ], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "ShortStrings" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol": { - "lastModificationDate": 1754306764465, - "contentHash": "86fd93657e4e27ff76c38699e9b9fcef", - "sourceName": "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "../Strings.sol" - ], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "MessageHashUtils" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/StorageSlot.sol": { - "lastModificationDate": 1754306760451, - "contentHash": "e656d64c4ce918f3d13030b91c935134", - "sourceName": "@openzeppelin/contracts/utils/StorageSlot.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "StorageSlot" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "lastModificationDate": 1754306760451, - "contentHash": "a55fef2557b35bac18a1880d3c2e6740", - "sourceName": "@openzeppelin/contracts/utils/Strings.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "./math/Math.sol", - "./math/SafeCast.sol", - "./math/SignedMath.sol" - ], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "Strings" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/math/Math.sol": { + "/app/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { "lastModificationDate": 1754306764456, - "contentHash": "2b2665ae9bdb1af440658741a77fe213", - "sourceName": "@openzeppelin/contracts/utils/math/Math.sol", - "solcConfig": { - "version": "0.8.20", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "viaIR": true, - "evmVersion": "paris", - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "../Panic.sol", - "./SafeCast.sol" - ], - "versionPragmas": [ - "^0.8.20" - ], - "artifacts": [ - "Math" - ] - }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { - "lastModificationDate": 1754306764456, - "contentHash": "2adca1150f58fc6f3d1f0a0f22ee7cca", - "sourceName": "@openzeppelin/contracts/utils/math/SafeCast.sol", + "contentHash": "8f19f64d2adadf448840908bbaf431c8", + "sourceName": "@openzeppelin/contracts/token/ERC20/IERC20.sol", "solcConfig": { "version": "0.8.20", "settings": { @@ -854,13 +354,13 @@ "^0.8.20" ], "artifacts": [ - "SafeCast" + "IERC20" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "lastModificationDate": 1754306764456, - "contentHash": "ae3528afb8bdb0a7dcfba5b115ee8074", - "sourceName": "@openzeppelin/contracts/utils/math/SignedMath.sol", + "/app/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "lastModificationDate": 1754306768254, + "contentHash": "794db3115001aa372c79326fcfd44b1f", + "sourceName": "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol", "solcConfig": { "version": "0.8.20", "settings": { @@ -887,19 +387,19 @@ } }, "imports": [ - "./SafeCast.sol" + "../IERC20.sol" ], "versionPragmas": [ "^0.8.20" ], "artifacts": [ - "SignedMath" + "IERC20Metadata" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/Panic.sol": { - "lastModificationDate": 1754306760451, - "contentHash": "2133dc13536b4a6a98131e431fac59e1", - "sourceName": "@openzeppelin/contracts/utils/Panic.sol", + "/app/node_modules/@openzeppelin/contracts/utils/structs/Checkpoints.sol": { + "lastModificationDate": 1754306764456, + "contentHash": "657c6dfea3bae1af948de6113ba01cea", + "sourceName": "@openzeppelin/contracts/utils/structs/Checkpoints.sol", "solcConfig": { "version": "0.8.20", "settings": { @@ -925,15 +425,17 @@ } } }, - "imports": [], + "imports": [ + "../math/Math.sol" + ], "versionPragmas": [ "^0.8.20" ], "artifacts": [ - "Panic" + "Checkpoints" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/governance/utils/Votes.sol": { + "/app/node_modules/@openzeppelin/contracts/governance/utils/Votes.sol": { "lastModificationDate": 1754306764456, "contentHash": "95aceafdc639babdd22576e5e3774d64", "sourceName": "@openzeppelin/contracts/governance/utils/Votes.sol", @@ -979,10 +481,10 @@ "Votes" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/structs/Checkpoints.sol": { + "/app/node_modules/@openzeppelin/contracts/utils/math/Math.sol": { "lastModificationDate": 1754306764456, - "contentHash": "657c6dfea3bae1af948de6113ba01cea", - "sourceName": "@openzeppelin/contracts/utils/structs/Checkpoints.sol", + "contentHash": "2b2665ae9bdb1af440658741a77fe213", + "sourceName": "@openzeppelin/contracts/utils/math/Math.sol", "solcConfig": { "version": "0.8.20", "settings": { @@ -1009,16 +511,169 @@ } }, "imports": [ - "../math/Math.sol" + "../Panic.sol", + "./SafeCast.sol" ], "versionPragmas": [ "^0.8.20" ], "artifacts": [ - "Checkpoints" + "Math" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC5805.sol": { + "/app/node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { + "lastModificationDate": 1754306764456, + "contentHash": "2adca1150f58fc6f3d1f0a0f22ee7cca", + "sourceName": "@openzeppelin/contracts/utils/math/SafeCast.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "SafeCast" + ] + }, + "/app/node_modules/@openzeppelin/contracts/utils/Panic.sol": { + "lastModificationDate": 1754306760451, + "contentHash": "2133dc13536b4a6a98131e431fac59e1", + "sourceName": "@openzeppelin/contracts/utils/Panic.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "Panic" + ] + }, + "/app/node_modules/@openzeppelin/contracts/utils/Nonces.sol": { + "lastModificationDate": 1754306760451, + "contentHash": "c32d108058718efb9061b88e83a83f79", + "sourceName": "@openzeppelin/contracts/utils/Nonces.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "Nonces" + ] + }, + "/app/node_modules/@openzeppelin/contracts/utils/cryptography/EIP712.sol": { + "lastModificationDate": 1754306764456, + "contentHash": "8dbb261c55f358342798c4d1803d4f8e", + "sourceName": "@openzeppelin/contracts/utils/cryptography/EIP712.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [ + "./MessageHashUtils.sol", + "../ShortStrings.sol", + "../../interfaces/IERC5267.sol" + ], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "EIP712" + ] + }, + "/app/node_modules/@openzeppelin/contracts/interfaces/IERC5805.sol": { "lastModificationDate": 1754306760460, "contentHash": "65ba9f89b1057e2192e341b286d4e261", "sourceName": "@openzeppelin/contracts/interfaces/IERC5805.sol", @@ -1058,7 +713,7 @@ "IERC5805" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/types/Time.sol": { + "/app/node_modules/@openzeppelin/contracts/utils/types/Time.sol": { "lastModificationDate": 1754306764456, "contentHash": "d83e7814a059fc1287fd765f424ce004", "sourceName": "@openzeppelin/contracts/utils/types/Time.sol", @@ -1098,7 +753,239 @@ "Time" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/governance/utils/IVotes.sol": { + "/app/node_modules/@openzeppelin/contracts/interfaces/IERC5267.sol": { + "lastModificationDate": 1754306760460, + "contentHash": "94364524cb1a39dcbc3d3afff6d8e53e", + "sourceName": "@openzeppelin/contracts/interfaces/IERC5267.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "IERC5267" + ] + }, + "/app/node_modules/@openzeppelin/contracts/utils/ShortStrings.sol": { + "lastModificationDate": 1754306760451, + "contentHash": "94e7feaf138d08fb736e43ca0be9bf26", + "sourceName": "@openzeppelin/contracts/utils/ShortStrings.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [ + "./StorageSlot.sol" + ], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "ShortStrings" + ] + }, + "/app/node_modules/@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol": { + "lastModificationDate": 1754306764465, + "contentHash": "86fd93657e4e27ff76c38699e9b9fcef", + "sourceName": "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [ + "../Strings.sol" + ], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "MessageHashUtils" + ] + }, + "/app/node_modules/@openzeppelin/contracts/utils/StorageSlot.sol": { + "lastModificationDate": 1754306760451, + "contentHash": "e656d64c4ce918f3d13030b91c935134", + "sourceName": "@openzeppelin/contracts/utils/StorageSlot.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "StorageSlot" + ] + }, + "/app/node_modules/@openzeppelin/contracts/utils/Strings.sol": { + "lastModificationDate": 1754306760451, + "contentHash": "a55fef2557b35bac18a1880d3c2e6740", + "sourceName": "@openzeppelin/contracts/utils/Strings.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [ + "./math/Math.sol", + "./math/SafeCast.sol", + "./math/SignedMath.sol" + ], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "Strings" + ] + }, + "/app/node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { + "lastModificationDate": 1754306764456, + "contentHash": "ae3528afb8bdb0a7dcfba5b115ee8074", + "sourceName": "@openzeppelin/contracts/utils/math/SignedMath.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [ + "./SafeCast.sol" + ], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "SignedMath" + ] + }, + "/app/node_modules/@openzeppelin/contracts/governance/utils/IVotes.sol": { "lastModificationDate": 1754306764456, "contentHash": "905ffceb29869fee4b5a649abe7e2927", "sourceName": "@openzeppelin/contracts/governance/utils/IVotes.sol", @@ -1135,7 +1022,7 @@ "IVotes" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC6372.sol": { + "/app/node_modules/@openzeppelin/contracts/interfaces/IERC6372.sol": { "lastModificationDate": 1754306760460, "contentHash": "414cd6acf090e4009cf016ff62ecbd88", "sourceName": "@openzeppelin/contracts/interfaces/IERC6372.sol", @@ -1172,8 +1059,45 @@ "IERC6372" ] }, - "/home/alex/Digital_Legal_Entity(DLE)/backend/contracts/FactoryDeployer.sol": { - "lastModificationDate": 1754683537642, + "/app/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "lastModificationDate": 1754306768254, + "contentHash": "94ec15baf0d5df863f45b8f351937ec7", + "sourceName": "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol", + "solcConfig": { + "version": "0.8.20", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "imports": [], + "versionPragmas": [ + "^0.8.20" + ], + "artifacts": [ + "IERC20Permit" + ] + }, + "/app/contracts/FactoryDeployer.sol": { + "lastModificationDate": 1754685617489, "contentHash": "6161bbb21af830bc05d6acd8682d9678", "sourceName": "contracts/FactoryDeployer.sol", "solcConfig": { diff --git a/backend/contracts/DLE.sol b/backend/contracts/DLE.sol index 5a91b98..b4a37cc 100644 --- a/backend/contracts/DLE.sol +++ b/backend/contracts/DLE.sol @@ -63,7 +63,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { bytes operation; // операция для исполнения uint256 governanceChainId; // сеть голосования (Single-Chain Governance) uint256[] targetChains; // целевые сети для исполнения - uint256 timelock; // earliest execution timestamp (sec) uint256 snapshotTimepoint; // блок/временная точка для getPastVotes mapping(address => bool) hasVoted; } @@ -106,7 +105,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { event ProposalVoted(uint256 proposalId, address voter, bool support, uint256 votingPower); event ProposalExecuted(uint256 proposalId, bytes operation); event ProposalCancelled(uint256 proposalId, string reason); - event ProposalTimelockSet(uint256 proposalId, uint256 timelock); event ProposalTargetsSet(uint256 proposalId, uint256[] targetChains); event ProposalGovernanceChainSet(uint256 proposalId, uint256 governanceChainId); event ModuleAdded(bytes32 moduleId, address moduleAddress); @@ -192,29 +190,47 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { bytes memory _operation, uint256 _governanceChainId, uint256[] memory _targetChains, - uint256 _timelockDelay + uint256 /* _timelockDelay */ ) external returns (uint256) { require(balanceOf(msg.sender) > 0, "Must hold tokens to create proposal"); require(_duration > 0, "Duration must be positive"); require(supportedChains[_governanceChainId], "Chain not supported"); - require(_timelockDelay <= 365 days, "Timelock too big"); + // _timelockDelay параметр игнорируется; timelock вынесем в отдельный модуль + return _createProposalInternal( + _description, + _duration, + _operation, + _governanceChainId, + _targetChains, + msg.sender + ); + } + function _createProposalInternal( + string memory _description, + uint256 _duration, + bytes memory _operation, + uint256 _governanceChainId, + uint256[] memory _targetChains, + address _initiator + ) internal returns (uint256) { uint256 proposalId = proposalCounter++; Proposal storage proposal = proposals[proposalId]; - + proposal.id = proposalId; proposal.description = _description; proposal.forVotes = 0; proposal.againstVotes = 0; proposal.executed = false; proposal.deadline = block.timestamp + _duration; - proposal.initiator = msg.sender; + proposal.initiator = _initiator; proposal.operation = _operation; proposal.governanceChainId = _governanceChainId; - proposal.timelock = block.timestamp + _timelockDelay; + // Снимок голосов: используем прошлую точку времени, чтобы getPastVotes был валиден в текущем блоке uint256 nowClock = clock(); proposal.snapshotTimepoint = nowClock == 0 ? 0 : nowClock - 1; + // запись целевых сетей for (uint256 i = 0; i < _targetChains.length; i++) { require(supportedChains[_targetChains[i]], "Target chain not supported"); @@ -222,10 +238,9 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { } allProposalIds.push(proposalId); - emit ProposalCreated(proposalId, msg.sender, _description); + emit ProposalCreated(proposalId, _initiator, _description); emit ProposalGovernanceChainSet(proposalId, _governanceChainId); emit ProposalTargetsSet(proposalId, _targetChains); - emit ProposalTimelockSet(proposalId, proposal.timelock); return proposalId; } @@ -297,7 +312,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { "Voting not ended and quorum not reached" ); require(passed && quorumReached, "Proposal not passed"); - require(block.timestamp >= proposal.timelock, "Timelock not expired"); proposal.executed = true; @@ -341,7 +355,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { require(!proposal.executed, "Proposal already executed in this chain"); require(currentChainId != proposal.governanceChainId, "Use executeProposal in governance chain"); require(_isTargetChain(proposal, currentChainId), "Chain not in targets"); - require(block.timestamp >= proposal.timelock, "Timelock not expired"); require(signers.length == signatures.length, "Bad signatures"); bytes32 opHash = keccak256(proposal.operation); @@ -620,24 +633,28 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { require(!activeModules[_moduleId], "Module already exists"); require(balanceOf(msg.sender) > 0, "Must hold tokens to create proposal"); - uint256 proposalId = proposalCounter++; - - Proposal storage proposal = proposals[proposalId]; - proposal.id = proposalId; - proposal.description = _description; - proposal.deadline = block.timestamp + _duration; - proposal.initiator = msg.sender; - - // Кодируем операцию добавления модуля + // Операция добавления модуля bytes memory operation = abi.encodeWithSelector( bytes4(keccak256("_addModule(bytes32,address)")), _moduleId, _moduleAddress ); - proposal.operation = operation; - emit ProposalCreated(proposalId, msg.sender, _description); - return proposalId; + // Целевые сети: по умолчанию все поддерживаемые сети + uint256[] memory targets = new uint256[](supportedChainIds.length); + for (uint256 i = 0; i < supportedChainIds.length; i++) { + targets[i] = supportedChainIds[i]; + } + + // Таймлок больше не используется в ядре; модуль Timelock будет добавлен отдельно + return _createProposalInternal( + _description, + _duration, + operation, + _chainId, + targets, + msg.sender + ); } /** @@ -657,23 +674,27 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { require(activeModules[_moduleId], "Module does not exist"); require(balanceOf(msg.sender) > 0, "Must hold tokens to create proposal"); - uint256 proposalId = proposalCounter++; - - Proposal storage proposal = proposals[proposalId]; - proposal.id = proposalId; - proposal.description = _description; - proposal.deadline = block.timestamp + _duration; - proposal.initiator = msg.sender; - - // Кодируем операцию удаления модуля + // Операция удаления модуля bytes memory operation = abi.encodeWithSelector( bytes4(keccak256("_removeModule(bytes32)")), _moduleId ); - proposal.operation = operation; - emit ProposalCreated(proposalId, msg.sender, _description); - return proposalId; + // Целевые сети: по умолчанию все поддерживаемые сети + uint256[] memory targets = new uint256[](supportedChainIds.length); + for (uint256 i = 0; i < supportedChainIds.length; i++) { + targets[i] = supportedChainIds[i]; + } + + // Таймлок больше не используется в ядре; модуль Timelock будет добавлен отдельно + return _createProposalInternal( + _description, + _duration, + operation, + _chainId, + targets, + msg.sender + ); } /** @@ -753,7 +774,7 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { uint256 deadline, address initiator, uint256 governanceChainId, - uint256 timelock, + uint256 snapshotTimepoint, uint256[] memory targets ) { @@ -769,7 +790,7 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { p.deadline, p.initiator, p.governanceChainId, - p.timelock, + p.snapshotTimepoint, p.targetChains ); @@ -818,7 +839,7 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard { if (p.executed) return 3; (bool passed, bool quorumReached) = checkProposalResult(_proposalId); bool votingOver = block.timestamp >= p.deadline; - bool ready = passed && quorumReached && block.timestamp >= p.timelock; + bool ready = passed && quorumReached; if (ready) return 5; // ReadyForExecution if (passed && (votingOver || quorumReached)) return 1; // Succeeded if (votingOver && !passed) return 2; // Defeated diff --git a/backend/db/migrations/037_seed_rpc_and_auth_tokens.sql b/backend/db/migrations/037_seed_rpc_and_auth_tokens.sql deleted file mode 100644 index 3d47cc5..0000000 --- a/backend/db/migrations/037_seed_rpc_and_auth_tokens.sql +++ /dev/null @@ -1,22 +0,0 @@ --- Миграция: наполнение таблиц rpc_providers и auth_tokens начальными значениями --- Пропускаем INSERT, так как данные должны быть зашифрованы - --- Добавление RPC-провайдеров (пропускаем, данные должны быть зашифрованы) --- INSERT INTO rpc_providers (network_id, rpc_url, chain_id) --- VALUES --- ('bsc', 'https://bsc-mainnet.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 56), --- ('ethereum', 'https://eth-mainnet.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 1), --- ('arbitrum', 'https://arb1.arbitrum.io/rpc', 42161), --- ('polygon', 'https://polygon.drpc.org', 137), --- ('sepolia', 'https://eth-sepolia.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 11155111) --- ON CONFLICT (network_id) DO NOTHING; - --- Добавление токенов для аутентификации админа (пропускаем, данные должны быть зашифрованы) --- INSERT INTO auth_tokens (name, address, network, min_balance) --- VALUES --- ('HB3A', '0x4b294265720b09ca39bfba18c7e368413c0f68eb', 'bsc', 10.0), --- ('HB3A', '0xd95a45fc46a7300e6022885afec3d618d7d3f27c', 'ethereum', 10.0), --- ('test2', '0xef49261169B454f191678D2aFC5E91Ad2e85dfD8', 'sepolia', 50.0), --- ('HB3A', '0x351f59de4fedbdf7601f5592b93db3b9330c1c1d', 'polygon', 10.0), --- ('HB3A', '0xdCe769b847a0a697239777D0B1C7dd33b6012ba0', 'arbitrum', 100.0) --- ON CONFLICT (address, network) DO NOTHING; \ No newline at end of file diff --git a/backend/db/migrations/050_create_secrets_table.sql b/backend/db/migrations/050_create_secrets_table.sql new file mode 100644 index 0000000..43262bc --- /dev/null +++ b/backend/db/migrations/050_create_secrets_table.sql @@ -0,0 +1,11 @@ +-- Create encrypted secrets storage +-- Stores key/value pairs where value is encrypted via encryptedDatabaseService + +CREATE TABLE IF NOT EXISTS public.secrets ( + key text PRIMARY KEY, + value_encrypted text, + created_at timestamptz DEFAULT CURRENT_TIMESTAMP, + updated_at timestamptz DEFAULT CURRENT_TIMESTAMP +); + + diff --git a/backend/routes/dleV2.js b/backend/routes/dleV2.js index dead433..83bc55c 100644 --- a/backend/routes/dleV2.js +++ b/backend/routes/dleV2.js @@ -19,6 +19,8 @@ const path = require('path'); const fs = require('fs'); const ethers = require('ethers'); // Added ethers for private key validation const create2 = require('../utils/create2'); +const verificationStore = require('../services/verificationStore'); +const etherscanV2 = require('../services/etherscanV2VerificationService'); /** * @route POST /api/dle-v2 @@ -92,6 +94,47 @@ router.get('/', async (req, res, next) => { } }); +/** + * @route POST /api/dle-v2/manual-card + * @desc Ручное сохранение карточки DLE по адресу (если деплой уже был) + * @access Private (admin) + */ +router.post('/manual-card', auth.requireAuth, auth.requireAdmin, async (req, res) => { + try { + const { dleAddress, name, symbol, location, coordinates, jurisdiction, oktmo, okvedCodes, kpp, quorumPercentage, initialPartners, initialAmounts, supportedChainIds, networks } = req.body || {}; + if (!dleAddress) { + return res.status(400).json({ success: false, message: 'dleAddress обязателен' }); + } + const data = { + name: name || '', + symbol: symbol || '', + location: location || '', + coordinates: coordinates || '', + jurisdiction: jurisdiction ?? 1, + oktmo: oktmo ?? null, + okvedCodes: Array.isArray(okvedCodes) ? okvedCodes : [], + kpp: kpp ?? null, + quorumPercentage: quorumPercentage ?? 51, + initialPartners: Array.isArray(initialPartners) ? initialPartners : [], + initialAmounts: Array.isArray(initialAmounts) ? initialAmounts : [], + governanceSettings: { + quorumPercentage: quorumPercentage ?? 51, + supportedChainIds: Array.isArray(supportedChainIds) ? supportedChainIds : [], + currentChainId: Array.isArray(supportedChainIds) && supportedChainIds.length ? supportedChainIds[0] : 1 + }, + dleAddress, + version: 'v2', + networks: Array.isArray(networks) ? networks : [], + createdAt: new Date().toISOString() + }; + const savedPath = dleV2Service.saveDLEData(data); + return res.json({ success: true, data: { file: savedPath } }); + } catch (e) { + logger.error('manual-card error', e); + return res.status(500).json({ success: false, message: e.message }); + } +}); + /** * @route GET /api/dle-v2/default-params * @desc Получить параметры по умолчанию для создания DLE v2 @@ -329,4 +372,145 @@ router.post('/predict-addresses', auth.requireAuth, auth.requireAdmin, async (re logger.error('predict-addresses error', e); return res.status(500).json({ success: false, message: 'Ошибка расчета адресов' }); } +}); + +// Сохранить GUID верификации (если нужно отдельным вызовом) +router.post('/verify/save-guid', auth.requireAuth, auth.requireAdmin, async (req, res) => { + try { + const { address, chainId, guid } = req.body || {}; + if (!address || !chainId || !guid) return res.status(400).json({ success: false, message: 'address, chainId, guid обязательны' }); + const data = verificationStore.updateChain(address, chainId, { guid, status: 'submitted' }); + return res.json({ success: true, data }); + } catch (e) { + return res.status(500).json({ success: false, message: e.message }); + } +}); + +// Получить статусы верификации по адресу DLE +router.get('/verify/status/:address', auth.requireAuth, async (req, res) => { + try { + const { address } = req.params; + const data = verificationStore.read(address); + return res.json({ success: true, data }); + } catch (e) { + return res.status(500).json({ success: false, message: e.message }); + } +}); + +// Обновить статусы верификации, опросив Etherscan V2 +router.post('/verify/refresh/:address', auth.requireAuth, auth.requireAdmin, async (req, res) => { + try { + const { address } = req.params; + let { etherscanApiKey } = req.body || {}; + if (!etherscanApiKey) { + try { + const { getSecret } = require('../services/secretStore'); + etherscanApiKey = await getSecret('ETHERSCAN_V2_API_KEY'); + } catch(_) {} + } + const data = verificationStore.read(address); + if (!data || !data.chains) return res.json({ success: true, data }); + + // Если guid отсутствует или ранее была ошибка chainid — попробуем автоматически переотправить верификацию (resubmit) + const needResubmit = Object.values(data.chains).some(c => !c.guid || /Missing or unsupported chainid/i.test(c.status || '')); + if (needResubmit && etherscanApiKey) { + // Найти карточку DLE + const list = dleV2Service.getAllDLEs(); + const card = list.find(x => x?.dleAddress && x.dleAddress.toLowerCase() === address.toLowerCase()); + if (card) { + const deployParams = { + name: card.name, + symbol: card.symbol, + location: card.location, + coordinates: card.coordinates, + jurisdiction: card.jurisdiction, + oktmo: card.oktmo, + okvedCodes: Array.isArray(card.okvedCodes) ? card.okvedCodes : [], + kpp: card.kpp, + quorumPercentage: card.quorumPercentage, + initialPartners: Array.isArray(card.initialPartners) ? card.initialPartners : [], + initialAmounts: Array.isArray(card.initialAmounts) ? card.initialAmounts : [], + supportedChainIds: Array.isArray(card.networks) ? card.networks.map(n => n.chainId).filter(Boolean) : (card.governanceSettings?.supportedChainIds || []), + currentChainId: card.governanceSettings?.currentChainId || (Array.isArray(card.networks) && card.networks[0]?.chainId) || 1 + }; + const deployResult = { success: true, data: { dleAddress: card.dleAddress, networks: card.networks || [] } }; + try { + await dleV2Service.autoVerifyAcrossChains({ deployParams, deployResult, apiKey: etherscanApiKey }); + } catch (_) {} + } + } + + // Далее — обычный опрос по имеющимся guid + const latest = verificationStore.read(address); + const chains = Object.values(latest.chains); + for (const c of chains) { + if (!c.guid || !c.chainId) continue; + try { + const st = await etherscanV2.checkStatus(c.chainId, c.guid, etherscanApiKey); + verificationStore.updateChain(address, c.chainId, { status: st?.result || st?.message || 'unknown' }); + } catch (e) { + verificationStore.updateChain(address, c.chainId, { status: `error: ${e.message}` }); + } + } + const updated = verificationStore.read(address); + return res.json({ success: true, data: updated }); + } catch (e) { + return res.status(500).json({ success: false, message: e.message }); + } +}); + +// Повторно отправить верификацию на Etherscan V2 для уже созданного DLE +router.post('/verify/resubmit/:address', auth.requireAuth, auth.requireAdmin, async (req, res) => { + try { + const { address } = req.params; + const { etherscanApiKey } = req.body || {}; + if (!etherscanApiKey && !process.env.ETHERSCAN_API_KEY) { + return res.status(400).json({ success: false, message: 'etherscanApiKey обязателен' }); + } + // Найти карточку DLE по адресу + const list = dleV2Service.getAllDLEs(); + const card = list.find(x => x?.dleAddress && x.dleAddress.toLowerCase() === address.toLowerCase()); + if (!card) return res.status(404).json({ success: false, message: 'Карточка DLE не найдена' }); + + // Сформировать deployParams из карточки + const deployParams = { + name: card.name, + symbol: card.symbol, + location: card.location, + coordinates: card.coordinates, + jurisdiction: card.jurisdiction, + oktmo: card.oktmo, + okvedCodes: Array.isArray(card.okvedCodes) ? card.okvedCodes : [], + kpp: card.kpp, + quorumPercentage: card.quorumPercentage, + initialPartners: Array.isArray(card.initialPartners) ? card.initialPartners : [], + initialAmounts: Array.isArray(card.initialAmounts) ? card.initialAmounts : [], + supportedChainIds: Array.isArray(card.networks) ? card.networks.map(n => n.chainId).filter(Boolean) : (card.governanceSettings?.supportedChainIds || []), + currentChainId: card.governanceSettings?.currentChainId || (Array.isArray(card.networks) && card.networks[0]?.chainId) || 1 + }; + + // Сформировать deployResult из карточки + const deployResult = { success: true, data: { dleAddress: card.dleAddress, networks: card.networks || [] } }; + + await dleV2Service.autoVerifyAcrossChains({ deployParams, deployResult, apiKey: etherscanApiKey }); + const updated = verificationStore.read(address); + return res.json({ success: true, data: updated }); + } catch (e) { + return res.status(500).json({ success: false, message: e.message }); + } +}); + +// Предварительная проверка балансов во всех выбранных сетях +router.post('/precheck', auth.requireAuth, auth.requireAdmin, async (req, res) => { + try { + const { supportedChainIds, privateKey } = req.body || {}; + if (!privateKey) return res.status(400).json({ success: false, message: 'Приватный ключ не передан' }); + if (!Array.isArray(supportedChainIds) || supportedChainIds.length === 0) { + return res.status(400).json({ success: false, message: 'Не переданы сети для проверки' }); + } + const result = await dleV2Service.checkBalances(supportedChainIds, privateKey); + return res.json({ success: true, data: result }); + } catch (e) { + return res.status(500).json({ success: false, message: e.message }); + } }); \ No newline at end of file diff --git a/backend/scripts/deploy/deploy-multichain.js b/backend/scripts/deploy/deploy-multichain.js index 12fef56..a99478a 100644 --- a/backend/scripts/deploy/deploy-multichain.js +++ b/backend/scripts/deploy/deploy-multichain.js @@ -2,25 +2,159 @@ const hre = require('hardhat'); const path = require('path'); -async function deployInNetwork(rpcUrl, pk, salt, initCodeHash, factoryAddress, dleInit) { +// Подбираем безопасные gas/fee для разных сетей (включая L2) +async function getFeeOverrides(provider, { minPriorityGwei = 1n, minFeeGwei = 20n } = {}) { + const fee = await provider.getFeeData(); + const overrides = {}; + const minPriority = (await (async () => hre.ethers.parseUnits(minPriorityGwei.toString(), 'gwei'))()); + const minFee = (await (async () => hre.ethers.parseUnits(minFeeGwei.toString(), 'gwei'))()); + if (fee.maxFeePerGas) { + overrides.maxFeePerGas = fee.maxFeePerGas < minFee ? minFee : fee.maxFeePerGas; + overrides.maxPriorityFeePerGas = (fee.maxPriorityFeePerGas && fee.maxPriorityFeePerGas > 0n) + ? fee.maxPriorityFeePerGas + : minPriority; + } else if (fee.gasPrice) { + overrides.gasPrice = fee.gasPrice < minFee ? minFee : fee.gasPrice; + } + return overrides; +} + +async function deployInNetwork(rpcUrl, pk, salt, initCodeHash, targetFactoryNonce, dleInit) { const { ethers } = hre; const provider = new ethers.JsonRpcProvider(rpcUrl); const wallet = new ethers.Wallet(pk, provider); + const net = await provider.getNetwork(); - // Ensure factory - let faddr = factoryAddress; - const code = faddr ? await provider.getCode(faddr) : '0x'; - if (!faddr || code === '0x') { - const Factory = await hre.ethers.getContractFactory('FactoryDeployer', wallet); - const factory = await Factory.deploy(); - await factory.waitForDeployment(); - faddr = await factory.getAddress(); + // DEBUG: базовая информация по сети + try { + const calcInitHash = ethers.keccak256(dleInit); + const saltLen = ethers.getBytes(salt).length; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} rpc=${rpcUrl}`); + console.log(`[MULTI_DBG] wallet=${wallet.address} targetFactoryNonce=${targetFactoryNonce}`); + console.log(`[MULTI_DBG] saltLenBytes=${saltLen} salt=${salt}`); + console.log(`[MULTI_DBG] initCodeHash(provided)=${initCodeHash}`); + console.log(`[MULTI_DBG] initCodeHash(calculated)=${calcInitHash}`); + console.log(`[MULTI_DBG] dleInit.lenBytes=${ethers.getBytes(dleInit).length} head16=${dleInit.slice(0, 34)}...`); + } catch (e) { + console.log('[MULTI_DBG] precheck error', e?.message || e); + } + + // 1) Выравнивание nonce до targetFactoryNonce нулевыми транзакциями (если нужно) + let current = await provider.getTransactionCount(wallet.address, 'pending'); + if (current > targetFactoryNonce) { + throw new Error(`Current nonce ${current} > targetFactoryNonce ${targetFactoryNonce} on chainId=${Number(net.chainId)}`); + } + while (current < targetFactoryNonce) { + const overrides = await getFeeOverrides(provider); + let gasLimit = 50000; // некоторые L2 требуют >21000 + let sent = false; + let lastErr = null; + for (let attempt = 0; attempt < 2 && !sent; attempt++) { + try { + const txReq = { + to: wallet.address, + value: 0n, + nonce: current, + gasLimit, + ...overrides + }; + const txFill = await wallet.sendTransaction(txReq); + await txFill.wait(); + sent = true; + } catch (e) { + lastErr = e; + if (String(e?.message || '').toLowerCase().includes('intrinsic gas too low') && attempt === 0) { + gasLimit = 100000; // поднимаем лимит и пробуем ещё раз + continue; + } + throw e; + } + } + if (!sent) throw lastErr || new Error('filler tx failed'); + current++; + } + + // 2) Деплой FactoryDeployer на согласованном nonce + const FactoryCF = await hre.ethers.getContractFactory('FactoryDeployer', wallet); + const feeOverrides = await getFeeOverrides(provider); + const factoryContract = await FactoryCF.deploy({ nonce: targetFactoryNonce, ...feeOverrides }); + await factoryContract.waitForDeployment(); + const factoryAddress = await factoryContract.getAddress(); + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} FactoryDeployer.address=${factoryAddress}`); + + // 3) Деплой DLE через CREATE2 + const Factory = await hre.ethers.getContractAt('FactoryDeployer', factoryAddress, wallet); + const n = await provider.getTransactionCount(wallet.address, 'pending'); + let tx; + try { + // Предварительная проверка конструктора вне CREATE2 (даст явную причину, если он ревертится) + try { + await wallet.estimateGas({ data: dleInit }); + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} predeploy(estGas) ok for constructor`); + } catch (e) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} predeploy(estGas) failed: ${e?.reason || e?.shortMessage || e?.message || e}`); + if (e?.data) console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} predeploy revert data: ${e.data}`); + } + // Оцениваем газ и добавляем запас + const est = await Factory.deploy.estimateGas(salt, dleInit, { nonce: n, ...feeOverrides }).catch(() => null); + // Рассчитываем доступный gasLimit из баланса + let gasLimit; + try { + const balance = await provider.getBalance(wallet.address, 'latest'); + const effPrice = feeOverrides.maxFeePerGas || feeOverrides.gasPrice || 0n; + const reserve = hre.ethers.parseEther('0.005'); + const maxByBalance = effPrice > 0n && balance > reserve ? (balance - reserve) / effPrice : 3_000_000n; + const fallbackGas = maxByBalance > 5_000_000n ? 5_000_000n : (maxByBalance < 2_500_000n ? 2_500_000n : maxByBalance); + gasLimit = est ? (est + est / 5n) : fallbackGas; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} estGas=${est?.toString?.()||'null'} effGasPrice=${effPrice?.toString?.()||'0'} maxByBalance=${maxByBalance.toString()} chosenGasLimit=${gasLimit.toString()}`); + } catch (_) { + const fallbackGas = 3_000_000n; + gasLimit = est ? (est + est / 5n) : fallbackGas; + } + // DEBUG: ожидаемый адрес через computeAddress + try { + const predicted = await Factory.computeAddress(salt, initCodeHash); + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} predictedAddress=${predicted}`); + // Idempotency: если уже есть код по адресу, пропускаем деплой + const code = await provider.getCode(predicted); + if (code && code !== '0x') { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} code already exists at predictedAddress, skip deploy`); + return { factory: factoryAddress, address: predicted, chainId: Number(net.chainId) }; + } + } catch (e) { + console.log('[MULTI_DBG] computeAddress(before) error', e?.message || e); + } + tx = await Factory.deploy(salt, dleInit, { nonce: n, gasLimit, ...feeOverrides }); + } catch (e) { + const n2 = await provider.getTransactionCount(wallet.address, 'pending'); + const est2 = await Factory.deploy.estimateGas(salt, dleInit, { nonce: n2, ...feeOverrides }).catch(() => null); + let gasLimit2; + try { + const balance2 = await provider.getBalance(wallet.address, 'latest'); + const effPrice2 = feeOverrides.maxFeePerGas || feeOverrides.gasPrice || 0n; + const reserve2 = hre.ethers.parseEther('0.005'); + const maxByBalance2 = effPrice2 > 0n && balance2 > reserve2 ? (balance2 - reserve2) / effPrice2 : 3_000_000n; + const fallbackGas2 = maxByBalance2 > 5_000_000n ? 5_000_000n : (maxByBalance2 < 2_500_000n ? 2_500_000n : maxByBalance2); + gasLimit2 = est2 ? (est2 + est2 / 5n) : fallbackGas2; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} RETRY estGas=${est2?.toString?.()||'null'} effGasPrice=${effPrice2?.toString?.()||'0'} maxByBalance=${maxByBalance2.toString()} chosenGasLimit=${gasLimit2.toString()}`); + } catch (_) { + gasLimit2 = est2 ? (est2 + est2 / 5n) : 3_000_000n; + } + console.log(`[MULTI_DBG] retry deploy with nonce=${n2} gasLimit=${gasLimit2?.toString?.() || 'auto'}`); + console.log(`[MULTI_DBG] deploy error(first) ${e?.message || e}`); + tx = await Factory.deploy(salt, dleInit, { nonce: n2, gasLimit: gasLimit2, ...feeOverrides }); } - const Factory = await hre.ethers.getContractAt('FactoryDeployer', faddr, wallet); - const tx = await Factory.deploy(salt, dleInit); const rc = await tx.wait(); - const addr = rc.logs?.[0]?.args?.addr || (await Factory.computeAddress(salt, initCodeHash)); - return { factory: faddr, address: addr }; + let addr = rc.logs?.[0]?.args?.addr; + if (!addr) { + try { + addr = await Factory.computeAddress(salt, initCodeHash); + } catch (e) { + console.log('[MULTI_DBG] computeAddress(after) error', e?.message || e); + } + } + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} deployedAddress=${addr}`); + return { factory: factoryAddress, address: addr, chainId: Number(net.chainId) }; } async function main() { @@ -31,7 +165,10 @@ async function main() { const networks = (process.env.MULTICHAIN_RPC_URLS || '').split(',').map(s => s.trim()).filter(Boolean); const factories = (process.env.MULTICHAIN_FACTORY_ADDRESSES || '').split(',').map(s => s.trim()); - if (!pk || !salt || !initCodeHash || networks.length === 0) throw new Error('Env: PRIVATE_KEY, CREATE2_SALT, INIT_CODE_HASH, MULTICHAIN_RPC_URLS'); + if (!pk) throw new Error('Env: PRIVATE_KEY'); + if (!salt) throw new Error('Env: CREATE2_SALT'); + if (!initCodeHash) throw new Error('Env: INIT_CODE_HASH'); + if (networks.length === 0) throw new Error('Env: MULTICHAIN_RPC_URLS'); // Prepare init code once const paramsPath = path.join(__dirname, './current-params.json'); @@ -53,12 +190,33 @@ async function main() { }; const deployTx = await DLE.getDeployTransaction(dleConfig, params.currentChainId); const dleInit = deployTx.data; + // DEBUG: глобальные значения + try { + const calcInitHash = ethers.keccak256(dleInit); + const saltLen = ethers.getBytes(salt).length; + console.log(`[MULTI_DBG] GLOBAL saltLenBytes=${saltLen} salt=${salt}`); + console.log(`[MULTI_DBG] GLOBAL initCodeHash(provided)=${initCodeHash}`); + console.log(`[MULTI_DBG] GLOBAL initCodeHash(calculated)=${calcInitHash}`); + console.log(`[MULTI_DBG] GLOBAL dleInit.lenBytes=${ethers.getBytes(dleInit).length} head16=${dleInit.slice(0, 34)}...`); + } catch (e) { + console.log('[MULTI_DBG] GLOBAL precheck error', e?.message || e); + } + + // Подготовим провайдеры и вычислим общий nonce для фабрики + const providers = networks.map(u => new hre.ethers.JsonRpcProvider(u)); + const wallets = providers.map(p => new hre.ethers.Wallet(pk, p)); + const nonces = []; + for (let i = 0; i < providers.length; i++) { + const n = await providers[i].getTransactionCount(wallets[i].address, 'pending'); + nonces.push(n); + } + const targetFactoryNonce = Math.max(...nonces); + console.log(`[MULTI_DBG] nonces=${JSON.stringify(nonces)} targetFactoryNonce=${targetFactoryNonce}`); const results = []; for (let i = 0; i < networks.length; i++) { const rpcUrl = networks[i]; - const factory = factories[i] || process.env.FACTORY_ADDRESS || null; - const r = await deployInNetwork(rpcUrl, pk, salt, initCodeHash, factory, dleInit); + const r = await deployInNetwork(rpcUrl, pk, salt, initCodeHash, targetFactoryNonce, dleInit); results.push({ rpcUrl, ...r }); } console.log('MULTICHAIN_DEPLOY_RESULT', JSON.stringify(results)); diff --git a/backend/services/dleV2Service.js b/backend/services/dleV2Service.js index 9bc22e6..07ff0a3 100644 --- a/backend/services/dleV2Service.js +++ b/backend/services/dleV2Service.js @@ -16,6 +16,8 @@ const fs = require('fs'); const { ethers } = require('ethers'); const logger = require('../utils/logger'); const { getRpcUrlByChainId } = require('./rpcProviderService'); +const etherscanV2 = require('./etherscanV2VerificationService'); +const verificationStore = require('./verificationStore'); /** * Сервис для управления DLE v2 (Digital Legal Entity) @@ -28,6 +30,8 @@ class DLEV2Service { * @returns {Promise} - Результат создания DLE */ async createDLE(dleParams) { + let paramsFile = null; + let tempParamsFile = null; try { logger.info('Начало создания DLE v2 с параметрами:', dleParams); @@ -38,10 +42,10 @@ class DLEV2Service { const deployParams = this.prepareDeployParams(dleParams); // Сохраняем параметры во временный файл - const paramsFile = this.saveParamsToFile(deployParams); + paramsFile = this.saveParamsToFile(deployParams); // Копируем параметры во временный файл с предсказуемым именем - const tempParamsFile = path.join(__dirname, '../scripts/deploy/current-params.json'); + tempParamsFile = path.join(__dirname, '../scripts/deploy/current-params.json'); const deployDir = path.dirname(tempParamsFile); if (!fs.existsSync(deployDir)) { fs.mkdirSync(deployDir, { recursive: true }); @@ -64,8 +68,9 @@ class DLEV2Service { { const { ethers } = require('ethers'); const provider = new ethers.JsonRpcProvider(rpcUrls[0]); - const walletAddress = dleParams.privateKey ? new ethers.Wallet(dleParams.privateKey, provider).address : null; - if (walletAddress) { + if (dleParams.privateKey) { + const pk = dleParams.privateKey.startsWith('0x') ? dleParams.privateKey : `0x${dleParams.privateKey}`; + const walletAddress = new ethers.Wallet(pk, provider).address; const balance = await provider.getBalance(walletAddress); const minBalance = ethers.parseEther("0.00001"); logger.info(`Баланс кошелька ${walletAddress}: ${ethers.formatEther(balance)} ETH`); @@ -85,22 +90,90 @@ class DLEV2Service { const factoryAddresses = deployParams.supportedChainIds.map(cid => process.env[`FACTORY_ADDRESS_${cid}`] || '').join(','); // Мультисетевой деплой одним вызовом + // Генерируем одноразовый CREATE2_SALT и сохраняем его с уникальным ключом в secrets + const { createAndStoreNewCreate2Salt } = require('./secretStore'); + const { salt: create2Salt, key: saltKey } = await createAndStoreNewCreate2Salt({ label: deployParams.name || 'DLEv2' }); + logger.info(`CREATE2_SALT создан и сохранён: key=${saltKey}`); + const result = await this.runDeployMultichain(paramsFile, { rpcUrls: rpcUrls.join(','), - privateKey: dleParams.privateKey, - salt: process.env.CREATE2_SALT, + privateKey: dleParams.privateKey?.startsWith('0x') ? dleParams.privateKey : `0x${dleParams.privateKey}`, + salt: create2Salt, initCodeHash, factories: factoryAddresses }); - // Очищаем временные файлы - this.cleanupTempFiles(paramsFile, tempParamsFile); + // Сохраняем информацию о созданном DLE для отображения на странице управления + try { + const firstNet = Array.isArray(result?.data?.networks) && result.data.networks.length > 0 ? result.data.networks[0] : null; + const dleData = { + name: deployParams.name, + symbol: deployParams.symbol, + location: deployParams.location, + coordinates: deployParams.coordinates, + jurisdiction: deployParams.jurisdiction, + oktmo: deployParams.oktmo, + okvedCodes: deployParams.okvedCodes || [], + kpp: deployParams.kpp, + quorumPercentage: deployParams.quorumPercentage, + initialPartners: deployParams.initialPartners || [], + initialAmounts: deployParams.initialAmounts || [], + governanceSettings: { + quorumPercentage: deployParams.quorumPercentage, + supportedChainIds: deployParams.supportedChainIds, + currentChainId: deployParams.currentChainId + }, + dleAddress: (result?.data?.dleAddress) || (firstNet?.address) || null, + version: 'v2', + networks: result?.data?.networks || [], + createdAt: new Date().toISOString() + }; + if (dleData.dleAddress) { + this.saveDLEData(dleData); + } + } catch (e) { + logger.warn('Не удалось сохранить локальную карточку DLE:', e.message); + } + + // Сохраняем ключ Etherscan V2 для последующих авто‑обновлений статуса, если он передан + try { + if (dleParams.etherscanApiKey) { + const { setSecret } = require('./secretStore'); + await setSecret('ETHERSCAN_V2_API_KEY', dleParams.etherscanApiKey); + } + } catch (_) {} + + // Авто-верификация через Etherscan V2 (опционально) + if (dleParams.autoVerifyAfterDeploy) { + try { + await this.autoVerifyAcrossChains({ + deployParams, + deployResult: result, + apiKey: dleParams.etherscanApiKey + }); + } catch (e) { + logger.warn('Авто-верификация завершилась с ошибкой:', e.message); + } + } return result; } catch (error) { logger.error('Ошибка при создании DLE v2:', error); throw error; + } finally { + try { + if (paramsFile || tempParamsFile) { + this.cleanupTempFiles(paramsFile, tempParamsFile); + } + } catch (e) { + logger.warn('Ошибка при очистке временных файлов (finally):', e.message); + } + try { + this.pruneOldTempFiles(24 * 60 * 60 * 1000); + } catch (e) { + logger.warn('Ошибка при автоочистке старых временных файлов:', e.message); + } } } @@ -154,6 +227,56 @@ class DLEV2Service { } } + /** + * Сохраняет/обновляет локальную карточку DLE для отображения в UI + * @param {Object} dleData + * @returns {string} Путь к сохраненному файлу + */ + saveDLEData(dleData) { + try { + if (!dleData || !dleData.dleAddress) { + throw new Error('Неверные данные для сохранения карточки DLE: отсутствует dleAddress'); + } + const dlesDir = path.join(__dirname, '../contracts-data/dles'); + if (!fs.existsSync(dlesDir)) { + fs.mkdirSync(dlesDir, { recursive: true }); + } + + // Если уже есть файл с таким адресом — обновим его + let targetFile = null; + try { + const files = fs.readdirSync(dlesDir); + for (const file of files) { + if (file.endsWith('.json') && file.includes('dle-v2-')) { + const fp = path.join(dlesDir, file); + try { + const existing = JSON.parse(fs.readFileSync(fp, 'utf8')); + if (existing?.dleAddress && existing.dleAddress.toLowerCase() === dleData.dleAddress.toLowerCase()) { + targetFile = fp; + // Совмещаем данные (не удаляя существующие поля сетей/верификации, если присутствуют) + dleData = { ...existing, ...dleData }; + break; + } + } catch (_) {} + } + } + } catch (_) {} + + if (!targetFile) { + const ts = new Date().toISOString().replace(/[:.]/g, '-'); + const fileName = `dle-v2-${ts}.json`; + targetFile = path.join(dlesDir, fileName); + } + + fs.writeFileSync(targetFile, JSON.stringify(dleData, null, 2)); + logger.info(`Карточка DLE сохранена: ${targetFile}`); + return targetFile; + } catch (e) { + logger.error('Ошибка сохранения карточки DLE:', e); + throw e; + } + } + /** * Подготавливает параметры для деплоя * @param {Object} params - Параметры DLE из формы @@ -165,11 +288,27 @@ class DLEV2Service { // Преобразуем суммы из строк или чисел в BigNumber, если нужно if (deployParams.initialAmounts && Array.isArray(deployParams.initialAmounts)) { - deployParams.initialAmounts = deployParams.initialAmounts.map(amount => { - if (typeof amount === 'string' && !amount.startsWith('0x')) { - return ethers.parseEther(amount).toString(); + deployParams.initialAmounts = deployParams.initialAmounts.map(rawAmount => { + // Принимаем как строки, так и числа; конвертируем в base units (18 знаков) + try { + if (typeof rawAmount === 'number' && Number.isFinite(rawAmount)) { + return ethers.parseUnits(rawAmount.toString(), 18).toString(); + } + if (typeof rawAmount === 'string') { + const a = rawAmount.trim(); + if (a.startsWith('0x')) { + // Уже base units (hex BigNumber) — оставляем как есть + return BigInt(a).toString(); + } + // Десятичная строка — конвертируем в base units + return ethers.parseUnits(a, 18).toString(); + } + // BigInt или иные типы — приводим к строке без изменения масштаба + return rawAmount.toString(); + } catch (e) { + // Фолбэк: безопасно привести к строке + return String(rawAmount); } - return amount.toString(); }); } @@ -294,8 +433,9 @@ class DLEV2Service { const m = stdout.match(/MULTICHAIN_DEPLOY_RESULT\s*(\[.*\])/s); if (!m) throw new Error('Результат не найден'); const arr = JSON.parse(m[1]); + if (!Array.isArray(arr) || arr.length === 0) throw new Error('Пустой результат деплоя'); const addr = arr[0].address; - const allSame = arr.every(x => x.address.toLowerCase() === addr.toLowerCase()); + const allSame = arr.every(x => x.address && x.address.toLowerCase() === addr.toLowerCase()); if (!allSame) throw new Error('Адреса отличаются между сетями'); resolve({ success: true, data: { dleAddress: addr, networks: arr } }); } catch (e) { @@ -348,6 +488,33 @@ class DLEV2Service { } } + /** + * Удаляет временные файлы параметров деплоя старше заданного возраста + * @param {number} maxAgeMs - Макс. возраст файлов в миллисекундах (по умолчанию 24ч) + */ + pruneOldTempFiles(maxAgeMs = 24 * 60 * 60 * 1000) { + const tempDir = path.join(__dirname, '../temp'); + try { + if (!fs.existsSync(tempDir)) return; + const now = Date.now(); + const files = fs.readdirSync(tempDir).filter(f => f.startsWith('dle-v2-params-') && f.endsWith('.json')); + for (const f of files) { + const fp = path.join(tempDir, f); + try { + const st = fs.statSync(fp); + if (now - st.mtimeMs > maxAgeMs) { + fs.unlinkSync(fp); + logger.info(`Удалён старый временный файл: ${fp}`); + } + } catch (e) { + logger.warn(`Не удалось обработать файл ${fp}: ${e.message}`); + } + } + } catch (e) { + logger.warn('Ошибка pruneOldTempFiles:', e.message); + } + } + /** * Получает список всех созданных DLE v2 * @returns {Array} - Список DLE v2 @@ -402,6 +569,191 @@ class DLEV2Service { const initCode = deployTx.data; return ethers.keccak256(initCode); } + + /** + * Проверяет баланс деплоера во всех выбранных сетях + * @param {number[]} chainIds + * @param {string} privateKey + * @returns {Promise<{balances: Array<{chainId:number, balanceEth:string, ok:boolean, rpcUrl:string}>, insufficient:number[]}>} + */ + async checkBalances(chainIds, privateKey) { + const { ethers } = require('ethers'); + const results = []; + const insufficient = []; + const normalizedPk = privateKey?.startsWith('0x') ? privateKey : `0x${privateKey}`; + for (const cid of chainIds || []) { + const rpcUrl = await getRpcUrlByChainId(cid); + if (!rpcUrl) { + results.push({ chainId: cid, balanceEth: '0', ok: false, rpcUrl: null }); + insufficient.push(cid); + continue; + } + try { + const provider = new ethers.JsonRpcProvider(rpcUrl); + const wallet = new ethers.Wallet(normalizedPk, provider); + const bal = await provider.getBalance(wallet.address); + // Минимум для деплоя; можно скорректировать + const min = ethers.parseEther('0.002'); + const ok = bal >= min; + results.push({ chainId: cid, balanceEth: ethers.formatEther(bal), ok, rpcUrl }); + if (!ok) insufficient.push(cid); + } catch (e) { + results.push({ chainId: cid, balanceEth: '0', ok: false, rpcUrl }); + insufficient.push(cid); + } + } + return { balances: results, insufficient }; + } + + /** + * Авто-верификация контракта во всех выбранных сетях через Etherscan V2 + * @param {Object} args + * @param {Object} args.deployParams + * @param {Object} args.deployResult - { success, data: { dleAddress, networks: [{rpcUrl,address}] } } + * @param {string} [args.apiKey] + */ + async autoVerifyAcrossChains({ deployParams, deployResult, apiKey }) { + if (!deployResult?.success) throw new Error('Нет результата деплоя для верификации'); + + // Подхватить ключ из secrets, если аргумент не передан + if (!apiKey) { + try { + const { getSecret } = require('./secretStore'); + apiKey = await getSecret('ETHERSCAN_V2_API_KEY'); + } catch (_) {} + } + + // Получаем компилер, standard-json-input и contractName из artifacts/build-info + const { standardJson, compilerVersion, contractName, constructorArgsHex } = await this.prepareVerificationPayload(deployParams); + + // Для каждой сети отправим верификацию, используя адрес из результата для соответствующего chainId + const chainIds = Array.isArray(deployParams.supportedChainIds) ? deployParams.supportedChainIds : []; + const netMap = new Map(); + if (Array.isArray(deployResult.data?.networks)) { + for (const n of deployResult.data.networks) { + if (n && typeof n.chainId === 'number') netMap.set(n.chainId, n.address); + } + } + for (const cid of chainIds) { + try { + const addrForChain = netMap.get(cid); + if (!addrForChain) { + logger.warn(`[AutoVerify] Нет адреса для chainId=${cid} в результате деплоя, пропускаю`); + continue; + } + const guid = await etherscanV2.submitVerification({ + chainId: cid, + contractAddress: addrForChain, + contractName, + compilerVersion, + standardJsonInput: standardJson, + constructorArgsHex, + apiKey + }); + logger.info(`[AutoVerify] Отправлена верификация в chainId=${cid}, guid=${guid}`); + verificationStore.updateChain(addrForChain, cid, { guid, status: 'submitted' }); + } catch (e) { + logger.warn(`[AutoVerify] Ошибка отправки верификации для chainId=${cid}: ${e.message}`); + const addrForChain = netMap.get(cid) || 'unknown'; + verificationStore.updateChain(addrForChain, cid, { status: `error: ${e.message}` }); + } + } + } + + /** + * Формирует стандартный JSON input, compilerVersion, contractName и ABI-кодированные аргументы конструктора + */ + async prepareVerificationPayload(params) { + const hre = require('hardhat'); + const path = require('path'); + const fs = require('fs'); + + // 1) Найти самый свежий build-info + const buildInfoDir = path.join(__dirname, '..', 'artifacts', 'build-info'); + let latestFile = null; + try { + const entries = fs.readdirSync(buildInfoDir).filter(f => f.endsWith('.json')); + let bestMtime = 0; + for (const f of entries) { + const fp = path.join(buildInfoDir, f); + const st = fs.statSync(fp); + if (st.mtimeMs > bestMtime) { bestMtime = st.mtimeMs; latestFile = fp; } + } + } catch (e) { + logger.warn('Артефакты build-info не найдены:', e.message); + } + + let standardJson = null; + let compilerVersion = null; + let sourcePathForDLE = 'contracts/DLE.sol'; + let contractName = 'contracts/DLE.sol:DLE'; + + if (latestFile) { + try { + const buildInfo = JSON.parse(fs.readFileSync(latestFile, 'utf8')); + // input — это стандартный JSON input для solc + standardJson = buildInfo.input || null; + // Версия компилятора + const long = buildInfo.solcLongVersion || buildInfo.solcVersion || hre.config.solidity?.version; + compilerVersion = long ? (long.startsWith('v') ? long : `v${long}`) : undefined; + + // Найти путь контракта DLE + if (buildInfo.output && buildInfo.output.contracts) { + for (const [filePathKey, contractsMap] of Object.entries(buildInfo.output.contracts)) { + if (contractsMap && contractsMap['DLE']) { + sourcePathForDLE = filePathKey; + contractName = `${filePathKey}:DLE`; + break; + } + } + } + } catch (e) { + logger.warn('Не удалось прочитать build-info:', e.message); + } + } + + // Если не нашли — fallback на config + if (!compilerVersion) compilerVersion = `v${hre.config.solidity.compilers?.[0]?.version || hre.config.solidity.version}`; + if (!standardJson) { + // fallback минимальная структура + standardJson = { + language: 'Solidity', + sources: { [sourcePathForDLE]: { content: '' } }, + settings: { optimizer: { enabled: true, runs: 200 } } + }; + } + + // 2) Посчитать ABI-код аргументов конструктора через сравнение с bytecode + // Конструктор: (dleConfig, currentChainId) + const Factory = await hre.ethers.getContractFactory('DLE'); + const dleConfig = { + name: params.name, + symbol: params.symbol, + location: params.location, + coordinates: params.coordinates, + jurisdiction: params.jurisdiction, + oktmo: params.oktmo, + okvedCodes: params.okvedCodes || [], + kpp: params.kpp, + quorumPercentage: params.quorumPercentage, + initialPartners: params.initialPartners, + initialAmounts: params.initialAmounts, + supportedChainIds: params.supportedChainIds + }; + const deployTx = await Factory.getDeployTransaction(dleConfig, params.currentChainId); + const fullData = deployTx.data; // 0x + creation bytecode + encoded args + const bytecode = Factory.bytecode; // 0x + creation bytecode + let constructorArgsHex; + try { + if (fullData && bytecode && fullData.startsWith(bytecode)) { + constructorArgsHex = '0x' + fullData.slice(bytecode.length); + } + } catch (e) { + logger.warn('Не удалось выделить constructorArguments из deployTx.data:', e.message); + } + + return { standardJson, compilerVersion, contractName, constructorArgsHex }; + } } module.exports = new DLEV2Service(); \ No newline at end of file diff --git a/backend/services/etherscanV2VerificationService.js b/backend/services/etherscanV2VerificationService.js new file mode 100644 index 0000000..a68d1b8 --- /dev/null +++ b/backend/services/etherscanV2VerificationService.js @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2024-2025 Тарабанов Александр Викторович + * All rights reserved. + * + * This software is proprietary and confidential. + * Unauthorized copying, modification, or distribution is prohibited. + * + * For licensing inquiries: info@hb3-accelerator.com + * Website: https://hb3-accelerator.com + * GitHub: https://github.com/HB3-ACCELERATOR + */ + +const axios = require('axios'); +const logger = require('../utils/logger'); + +const ETHERSCAN_V2_ENDPOINT = 'https://api.etherscan.io/v2/api'; + +class EtherscanV2VerificationService { + /** + * Отправить исходники контракта на верификацию (V2) + * Документация: https://docs.etherscan.io/etherscan-v2/contract-verification/multichain-verification + * @param {Object} opts + * @param {number} opts.chainId + * @param {string} opts.contractAddress + * @param {string} opts.contractName - формат "contracts/DLE.sol:DLE" + * @param {string} opts.compilerVersion - например, "v0.8.24+commit.e11b9ed9" + * @param {Object|string} opts.standardJsonInput - стандартный JSON input (рекомендуется) + * @param {string} [opts.constructorArgsHex] + * @param {string} [opts.apiKey] + * @returns {Promise} guid + */ + async submitVerification({ chainId, contractAddress, contractName, compilerVersion, standardJsonInput, constructorArgsHex, apiKey }) { + const key = apiKey || process.env.ETHERSCAN_API_KEY; + if (!key) throw new Error('ETHERSCAN_API_KEY не задан'); + if (!chainId) throw new Error('chainId обязателен'); + if (!contractAddress) throw new Error('contractAddress обязателен'); + if (!contractName) throw new Error('contractName обязателен'); + if (!compilerVersion) throw new Error('compilerVersion обязателен'); + if (!standardJsonInput) throw new Error('standardJsonInput обязателен'); + + const payload = new URLSearchParams(); + // Согласно V2, chainid должен передаваться в query, а не в теле формы + payload.set('module', 'contract'); + payload.set('action', 'verifysourcecode'); + payload.set('apikey', key); + payload.set('codeformat', 'solidity-standard-json-input'); + payload.set('sourceCode', typeof standardJsonInput === 'string' ? standardJsonInput : JSON.stringify(standardJsonInput)); + payload.set('contractaddress', contractAddress); + payload.set('contractname', contractName); + payload.set('compilerversion', compilerVersion); + if (constructorArgsHex) { + const no0x = constructorArgsHex.startsWith('0x') ? constructorArgsHex.slice(2) : constructorArgsHex; + payload.set('constructorArguments', no0x); + } + + const url = `${ETHERSCAN_V2_ENDPOINT}?chainid=${encodeURIComponent(String(chainId))}`; + const { data } = await axios.post(url, payload.toString(), { + headers: { 'Content-Type': 'application/x-www-form-urlencoded' } + }); + logger.info('[EtherscanV2] verifysourcecode response', data); + if (data && data.status === '1' && data.result) return data.result; // guid + throw new Error(data?.result || data?.message || 'Etherscan V2 verifysourcecode error'); + } + + /** + * Проверить статус верификации по guid + * @param {number} chainId + * @param {string} guid + * @param {string} [apiKey] + * @returns {Promise<{status:string,message:string,result:string}>} + */ + async checkStatus(chainId, guid, apiKey) { + const key = apiKey || process.env.ETHERSCAN_API_KEY; + if (!key) throw new Error('ETHERSCAN_API_KEY не задан'); + const params = new URLSearchParams(); + params.set('chainid', String(chainId)); + params.set('module', 'contract'); + params.set('action', 'checkverifystatus'); + params.set('guid', guid); + params.set('apikey', key); + const { data } = await axios.get(`${ETHERSCAN_V2_ENDPOINT}?${params.toString()}`); + logger.info('[EtherscanV2] checkverifystatus response', data); + return data; + } +} + +module.exports = new EtherscanV2VerificationService(); + + diff --git a/backend/services/rpcProviderService.js b/backend/services/rpcProviderService.js index 3b03a56..e406f00 100644 --- a/backend/services/rpcProviderService.js +++ b/backend/services/rpcProviderService.js @@ -12,6 +12,14 @@ const encryptedDb = require('./encryptedDatabaseService'); +function normalizeNetworkId(networkId) { + if (!networkId || typeof networkId !== 'string') return networkId; + const v = networkId.trim().toLowerCase(); + // Common normalizations + if (v === 'base sepolia testnet' || v === 'base sepolia') return 'base-sepolia'; + return v.replace(/\s+/g, '-'); +} + async function getAllRpcProviders() { const providers = await encryptedDb.getData('rpc_providers', {}, null, 'id'); return providers; @@ -24,7 +32,7 @@ async function saveAllRpcProviders(rpcConfigs) { // Сохраняем новые провайдеры for (const cfg of rpcConfigs) { await encryptedDb.saveData('rpc_providers', { - network_id: cfg.networkId, + network_id: normalizeNetworkId(cfg.networkId), rpc_url: cfg.rpcUrl, chain_id: cfg.chainId || null }); @@ -41,12 +49,12 @@ async function upsertRpcProvider(cfg) { rpc_url: cfg.rpcUrl, chain_id: cfg.chainId || null }, { - network_id: cfg.networkId + network_id: normalizeNetworkId(cfg.networkId) }); } else { // Создаем новый провайдер await encryptedDb.saveData('rpc_providers', { - network_id: cfg.networkId, + network_id: normalizeNetworkId(cfg.networkId), rpc_url: cfg.rpcUrl, chain_id: cfg.chainId || null }); @@ -58,8 +66,14 @@ async function deleteRpcProvider(networkId) { } async function getRpcUrlByNetworkId(networkId) { - const providers = await encryptedDb.getData('rpc_providers', { network_id: networkId }, 1); - return providers[0]?.rpc_url || null; + // Сначала пробуем точное совпадение (для обратной совместимости) + let providers = await encryptedDb.getData('rpc_providers', { network_id: networkId }, 1); + if (providers.length > 0) return providers[0].rpc_url || null; + // Затем ищем по нормализованному ключу среди всех записей + const all = await encryptedDb.getData('rpc_providers', {}, null, 'id'); + const norm = normalizeNetworkId(networkId); + const found = all.find(p => normalizeNetworkId(p.network_id) === norm); + return found ? found.rpc_url : null; } async function getRpcUrlByChainId(chainId) { diff --git a/backend/services/secretStore.js b/backend/services/secretStore.js new file mode 100644 index 0000000..2a67375 --- /dev/null +++ b/backend/services/secretStore.js @@ -0,0 +1,56 @@ +/** + * Lightweight encrypted secret store over encryptedDatabaseService + */ +const crypto = require('crypto'); +const encryptedDb = require('./encryptedDatabaseService'); + +const TABLE = 'secrets'; + +async function getSecret(key) { + const rows = await encryptedDb.getData(TABLE, { key }, 1); + return rows && rows[0] ? rows[0].value : null; +} + +async function setSecret(key, value) { + const existing = await encryptedDb.getData(TABLE, { key }, 1); + const payload = { key, value, updated_at: new Date() }; + if (existing && existing.length) { + await encryptedDb.saveData(TABLE, payload, { key }); + } else { + payload.created_at = new Date(); + await encryptedDb.saveData(TABLE, payload); + } + return value; +} + +async function getOrCreateCreate2Salt() { + let salt = await getSecret('CREATE2_SALT'); + if (salt && /^0x[0-9a-fA-F]{64}$/.test(salt)) return salt; + const hex = crypto.randomBytes(32).toString('hex'); + salt = '0x' + hex; + await setSecret('CREATE2_SALT', salt); + return salt; +} + +/** + * Генерирует одноразовый CREATE2 salt (0x + 32 байта) и сохраняет в secrets с уникальным ключом + * @param {Object} [opts] + * @param {string} [opts.prefix] Префикс ключа (по умолчанию CREATE2_SALT) + * @param {string} [opts.label] Доп. метка (например, имя DLE) + * @returns {Promise<{ salt: string, key: string }>} + */ +async function createAndStoreNewCreate2Salt(opts = {}) { + const prefix = opts.prefix || 'CREATE2_SALT'; + const label = (opts.label || '').replace(/[^a-zA-Z0-9_.:-]/g, '').slice(0, 40); + const hex = crypto.randomBytes(32).toString('hex'); + const salt = '0x' + hex; + const rand = crypto.randomBytes(2).toString('hex'); + const ts = new Date().toISOString().replace(/[:.]/g, '-'); + const key = [prefix, label, ts, rand].filter(Boolean).join(':'); + await setSecret(key, salt); + return { salt, key }; +} + +module.exports = { getSecret, setSecret, getOrCreateCreate2Salt, createAndStoreNewCreate2Salt }; + + diff --git a/backend/services/verificationStore.js b/backend/services/verificationStore.js new file mode 100644 index 0000000..286ed6e --- /dev/null +++ b/backend/services/verificationStore.js @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2024-2025 Тарабанов Александр Викторович + * All rights reserved. + */ + +const path = require('path'); +const fs = require('fs'); + +const baseDir = path.join(__dirname, '../contracts-data/verifications'); + +function ensureDir() { + if (!fs.existsSync(baseDir)) fs.mkdirSync(baseDir, { recursive: true }); +} + +function getFilePath(address) { + ensureDir(); + const key = String(address || '').toLowerCase(); + return path.join(baseDir, `${key}.json`); +} + +function read(address) { + const fp = getFilePath(address); + if (!fs.existsSync(fp)) return { address: String(address).toLowerCase(), chains: {} }; + try { + return JSON.parse(fs.readFileSync(fp, 'utf8')); + } catch { + return { address: String(address).toLowerCase(), chains: {} }; + } +} + +function write(address, data) { + const fp = getFilePath(address); + fs.writeFileSync(fp, JSON.stringify(data, null, 2)); +} + +function updateChain(address, chainId, patch) { + const data = read(address); + if (!data.chains) data.chains = {}; + const cid = String(chainId); + data.chains[cid] = { ...(data.chains[cid] || {}), ...patch, chainId: Number(chainId), updatedAt: new Date().toISOString() }; + write(address, data); + return data; +} + +module.exports = { read, write, updateChain }; + + diff --git a/decrypt-all-tables.sh b/decrypt-all-tables.sh deleted file mode 100755 index 941e254..0000000 --- a/decrypt-all-tables.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash - -# Скрипт для расшифровки всех таблиц -# Использование: ./decrypt-all-tables.sh - -ENCRYPTION_KEY=$(cat ./ssl/keys/full_db_encryption.key) - -echo "🔓 Расшифровка всех таблиц..." - -# Получаем список всех таблиц -TABLES=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " -SELECT table_name -FROM information_schema.tables -WHERE table_schema = 'public' -AND table_type = 'BASE TABLE' -ORDER BY table_name;") - -# Функция для расшифровки таблицы -decrypt_table() { - local table_name="$1" - echo "🔓 Расшифровка таблицы: $table_name" - - # Получаем зашифрованные колонки - local encrypted_columns=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " - SELECT column_name - FROM information_schema.columns - WHERE table_name = '$table_name' - AND table_schema = 'public' - AND column_name LIKE '%_encrypted' - ORDER BY ordinal_position;") - - if [ -z "$encrypted_columns" ]; then - echo " ⏭️ Нет зашифрованных колонок" - return - fi - - echo " 📝 Зашифрованные колонки:" - echo "$encrypted_columns" | while read -r column_name; do - if [ -n "$column_name" ]; then - echo " $column_name" - # Определяем тип колонки - data_type=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " - SELECT data_type FROM information_schema.columns - WHERE table_name = '$table_name' AND column_name = '$column_name' AND table_schema = 'public';" | xargs) - # Определяем первичный ключ для таблицы - primary_key=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " - SELECT column_name FROM information_schema.key_column_usage - WHERE table_name = '$table_name' AND constraint_name LIKE '%_pkey' - AND table_schema = 'public' LIMIT 1;" | xargs) - - if [ "$data_type" = "jsonb" ] || [ "$data_type" = "json" ]; then - # Расшифровываем json/jsonb - docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " - SELECT $primary_key, decrypt_json($column_name, '$ENCRYPTION_KEY') as ${column_name%_encrypted}_decrypted - FROM $table_name WHERE $column_name IS NOT NULL LIMIT 5;" - else - # Расшифровываем текстовые - docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " - SELECT $primary_key, decrypt_text($column_name, '$ENCRYPTION_KEY') as ${column_name%_encrypted}_decrypted - FROM $table_name WHERE $column_name IS NOT NULL LIMIT 5;" - fi - fi - done -} - -# Расшифровываем каждую таблицу -echo "$TABLES" | while read -r table_name; do - if [ -n "$table_name" ]; then - decrypt_table "$table_name" - fi -done - -echo "✅ Расшифровка завершена!" diff --git a/encrypt-database.sh b/encrypt-database.sh deleted file mode 100755 index f6692e1..0000000 --- a/encrypt-database.sh +++ /dev/null @@ -1,307 +0,0 @@ -#!/bin/bash - -# Скрипт для полного шифрования всех таблиц в базе данных DLE -# Использование: ./encrypt-all-tables.sh - -# Проверяем наличие OpenSSL -if ! command -v openssl &> /dev/null; then - echo "❌ OpenSSL не установлен. Установите: sudo apt-get install openssl" - exit 1 -fi - -# Создаём папку для ключей -mkdir -p ./ssl/keys - -# Генерируем ключ шифрования (если его нет) -if [ ! -f "./ssl/keys/full_db_encryption.key" ]; then - echo "🔑 Генерация ключа шифрования для всех таблиц..." - openssl rand -base64 32 > ./ssl/keys/full_db_encryption.key - chmod 600 ./ssl/keys/full_db_encryption.key - echo "✅ Ключ создан: ./ssl/keys/full_db_encryption.key" -fi - -echo "🔒 Полное шифрование всех таблиц в базе данных..." - -# Проверяем подключение к БД -if ! docker exec dapp-postgres pg_isready -U dapp_user -d dapp_db > /dev/null 2>&1; then - echo "❌ Не удалось подключиться к базе данных" - exit 1 -fi - -# Создаём функции шифрования в PostgreSQL -echo "📝 Создание функций шифрования в PostgreSQL..." - -docker exec dapp-postgres psql -U dapp_user -d dapp_db << 'EOF' --- Создаём расширение для шифрования -CREATE EXTENSION IF NOT EXISTS pgcrypto; - --- Функция для шифрования текста -CREATE OR REPLACE FUNCTION encrypt_text(data text, key text) -RETURNS text AS $$ -BEGIN - IF data IS NULL THEN - RETURN NULL; - END IF; - RETURN encode(encrypt_iv(data::bytea, decode(key, 'base64'), decode('000102030405060708090A0B0C0D0E0F', 'hex'), 'aes-cbc'), 'base64'); -END; -$$ LANGUAGE plpgsql; - --- Функция для расшифровки текста -CREATE OR REPLACE FUNCTION decrypt_text(encrypted_data text, key text) -RETURNS text AS $$ -BEGIN - IF encrypted_data IS NULL THEN - RETURN NULL; - END IF; - RETURN convert_from(decrypt_iv(decode(encrypted_data, 'base64'), decode(key, 'base64'), decode('000102030405060708090A0B0C0D0E0F', 'hex'), 'aes-cbc'), 'utf8'); -END; -$$ LANGUAGE plpgsql; - --- Функция для шифрования JSON -CREATE OR REPLACE FUNCTION encrypt_json(data jsonb, key text) -RETURNS text AS $$ -BEGIN - IF data IS NULL THEN - RETURN NULL; - END IF; - RETURN encode(encrypt_iv(data::text::bytea, decode(key, 'base64'), decode('000102030405060708090A0B0C0D0E0F', 'hex'), 'aes-cbc'), 'base64'); -END; -$$ LANGUAGE plpgsql; - --- Функция для расшифровки JSON -CREATE OR REPLACE FUNCTION decrypt_json(encrypted_data text, key text) -RETURNS jsonb AS $$ -BEGIN - IF encrypted_data IS NULL THEN - RETURN NULL; - END IF; - RETURN convert_from(decrypt_iv(decode(encrypted_data, 'base64'), decode(key, 'base64'), decode('000102030405060708090A0B0C0D0E0F', 'hex'), 'aes-cbc'), 'utf8')::jsonb; -END; -$$ LANGUAGE plpgsql; -EOF - -# Читаем ключ шифрования -ENCRYPTION_KEY=$(cat ./ssl/keys/full_db_encryption.key) - -echo "🔐 Начинаем шифрование всех таблиц..." - -# Получаем список всех таблиц -TABLES=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " -SELECT table_name -FROM information_schema.tables -WHERE table_schema = 'public' -AND table_type = 'BASE TABLE' -ORDER BY table_name;") - -echo "📋 Найдены таблицы для шифрования:" -echo "$TABLES" - -# Функция для шифрования таблицы -encrypt_table() { - local table_name="$1" - echo "🔐 Шифрование таблицы: $table_name" - - # Получаем информацию о колонках - local columns=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " - SELECT column_name, data_type - FROM information_schema.columns - WHERE table_name = '$table_name' - AND table_schema = 'public' - AND data_type IN ('text', 'varchar', 'character varying', 'json', 'jsonb') - AND column_name NOT LIKE '%_encrypted' - AND column_name NOT IN ('created_at', 'updated_at', 'id') - ORDER BY ordinal_position;") - - if [ -z "$columns" ]; then - echo " ⏭️ Нет текстовых колонок для шифрования" - return - fi - - echo " 📝 Колонки для шифрования:" - echo "$columns" | while read -r column_info; do - if [ -n "$column_info" ]; then - echo " $column_info" - fi - done - - # Создаём зашифрованные колонки и шифруем данные - echo "$columns" | while read -r column_info; do - if [ -n "$column_info" ]; then - column_name=$(echo "$column_info" | awk '{print $1}') - data_type=$(echo "$column_info" | awk '{print $2}') - - echo " 🔐 Шифрование колонки: $column_name" - - # Добавляем зашифрованную колонку - if [ "$data_type" = "jsonb" ] || [ "$data_type" = "json" ]; then - docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " - ALTER TABLE $table_name ADD COLUMN IF NOT EXISTS ${column_name}_encrypted TEXT; - UPDATE $table_name - SET ${column_name}_encrypted = encrypt_json($column_name, '$ENCRYPTION_KEY') - WHERE $column_name IS NOT NULL AND ${column_name}_encrypted IS NULL;" - else - docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " - ALTER TABLE $table_name ADD COLUMN IF NOT EXISTS ${column_name}_encrypted TEXT; - UPDATE $table_name - SET ${column_name}_encrypted = encrypt_text($column_name, '$ENCRYPTION_KEY') - WHERE $column_name IS NOT NULL AND ${column_name}_encrypted IS NULL;" - fi - fi - done -} - -# Шифруем каждую таблицу -echo "$TABLES" | while read -r table_name; do - if [ -n "$table_name" ]; then - encrypt_table "$table_name" - fi -done - -echo "✅ Шифрование всех таблиц завершено!" - -# Создаём скрипт для расшифровки -cat > decrypt-all-tables.sh << 'EOF' -#!/bin/bash - -# Скрипт для расшифровки всех таблиц -# Использование: ./decrypt-all-tables.sh - -ENCRYPTION_KEY=$(cat ./ssl/keys/full_db_encryption.key) - -echo "🔓 Расшифровка всех таблиц..." - -# Получаем список всех таблиц -TABLES=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " -SELECT table_name -FROM information_schema.tables -WHERE table_schema = 'public' -AND table_type = 'BASE TABLE' -ORDER BY table_name;") - -# Функция для расшифровки таблицы -decrypt_table() { - local table_name="$1" - echo "🔓 Расшифровка таблицы: $table_name" - - # Получаем зашифрованные колонки - local encrypted_columns=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " - SELECT column_name - FROM information_schema.columns - WHERE table_name = '$table_name' - AND table_schema = 'public' - AND column_name LIKE '%_encrypted' - ORDER BY ordinal_position;") - - if [ -z "$encrypted_columns" ]; then - echo " ⏭️ Нет зашифрованных колонок" - return - fi - - echo " 📝 Зашифрованные колонки:" - echo "$encrypted_columns" | while read -r column_name; do - if [ -n "$column_name" ]; then - echo " $column_name" - # Определяем тип колонки - data_type=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " - SELECT data_type FROM information_schema.columns - WHERE table_name = '$table_name' AND column_name = '$column_name' AND table_schema = 'public';" | xargs) - if [ "$data_type" = "jsonb" ] || [ "$data_type" = "json" ]; then - # Расшифровываем json/jsonb - docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " - SELECT id, decrypt_json($column_name, '$ENCRYPTION_KEY') as ${column_name%_encrypted}_decrypted - FROM $table_name WHERE $column_name IS NOT NULL LIMIT 5;" - else - # Расшифровываем текстовые - docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " - SELECT id, decrypt_text($column_name, '$ENCRYPTION_KEY') as ${column_name%_encrypted}_decrypted - FROM $table_name WHERE $column_name IS NOT NULL LIMIT 5;" - fi - fi - done -} - -# Расшифровываем каждую таблицу -echo "$TABLES" | while read -r table_name; do - if [ -n "$table_name" ]; then - decrypt_table "$table_name" - fi -done - -echo "✅ Расшифровка завершена!" -EOF - -chmod +x decrypt-all-tables.sh - -# Создаём скрипт для удаления незашифрованных колонок -cat > remove-unencrypted-columns.sh << 'EOF' -#!/bin/bash - -# Скрипт для удаления незашифрованных колонок -# ВНИМАНИЕ: Это необратимая операция! -# Использование: ./remove-unencrypted-columns.sh - -echo "⚠️ ВНИМАНИЕ: Это удалит все незашифрованные колонки!" -echo "Убедитесь, что шифрование работает корректно!" -read -p "Продолжить? (y/N): " -n 1 -r -echo -if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "❌ Операция отменена" - exit 1 -fi - -# Получаем список всех таблиц -TABLES=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " -SELECT table_name -FROM information_schema.tables -WHERE table_schema = 'public' -AND table_type = 'BASE TABLE' -ORDER BY table_name;") - -# Удаляем незашифрованные колонки -echo "$TABLES" | while read -r table_name; do - if [ -n "$table_name" ]; then - echo "🗑️ Удаление незашифрованных колонок в таблице: $table_name" - - # Получаем незашифрованные колонки - local unencrypted_columns=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " - SELECT column_name - FROM information_schema.columns - WHERE table_name = '$table_name' - AND table_schema = 'public' - AND data_type IN ('text', 'varchar', 'character varying', 'json', 'jsonb') - AND column_name NOT LIKE '%_encrypted' - AND column_name NOT IN ('created_at', 'updated_at', 'id') - ORDER BY ordinal_position;") - - echo "$unencrypted_columns" | while read -r column_name; do - if [ -n "$column_name" ]; then - echo " 🗑️ Удаление колонки: $column_name" - docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " - ALTER TABLE $table_name DROP COLUMN IF EXISTS $column_name;" - fi - done - fi -done - -echo "✅ Незашифрованные колонки удалены!" -EOF - -chmod +x remove-unencrypted-columns.sh - -echo "" -echo "🎯 Что было сделано:" -echo "1. ✅ Создан ключ шифрования: ./ssl/keys/full_db_encryption.key" -echo "2. ✅ Добавлены функции шифрования в PostgreSQL" -echo "3. ✅ Зашифрованы ВСЕ текстовые колонки во ВСЕХ таблицах" -echo "4. ✅ Создан скрипт расшифровки: ./decrypt-all-tables.sh" -echo "5. ✅ Создан скрипт удаления: ./remove-unencrypted-columns.sh" -echo "" -echo "⚠️ ВАЖНО:" -echo "- Ключ шифрования: ./ssl/keys/full_db_encryption.key" -echo "- Храните ключ в безопасном месте!" -echo "- Сделайте резервную копию ключа!" -echo "" -echo "🔧 Следующие шаги:" -echo "1. Протестируйте расшифровку: ./decrypt-all-tables.sh" -echo "2. Обновите код приложения для работы с зашифрованными данными" -echo "3. После проверки удалите незашифрованные колонки: ./remove-unencrypted-columns.sh" \ No newline at end of file diff --git a/frontend/src/views/ManagementView.vue b/frontend/src/views/ManagementView.vue index bfabba6..92888d6 100644 --- a/frontend/src/views/ManagementView.vue +++ b/frontend/src/views/ManagementView.vue @@ -75,6 +75,15 @@ +
+ Адреса по сетям: +
    +
  • + Chain {{ net.chainId }}: + {{ shortenAddress(net.address) }} +
  • +
+
Местоположение: {{ dle.location }}
@@ -91,6 +100,15 @@ Статус: Активен +
+ Верификация: +
    +
  • + Chain {{ chainId }}: {{ info.status || '—' }} (guid: {{ info.guid.slice(0,8) }}…) +
  • +
+ +
@@ -175,7 +193,7 @@ diff --git a/frontend/src/views/settings/DleDeployFormView.vue b/frontend/src/views/settings/DleDeployFormView.vue index 439fb1f..0f1fe26 100644 --- a/frontend/src/views/settings/DleDeployFormView.vue +++ b/frontend/src/views/settings/DleDeployFormView.vue @@ -558,6 +558,29 @@ + +
+
+ +
+ + +
+
+ +
+
+
+
💰 Требования к балансу:
@@ -684,61 +707,10 @@ 💰 Общая стоимость: ~${{ totalDeployCost.toFixed(2) }}
- -
-
- 📍 Предсказанные адреса DLE: -
-
    -
  • - {{ net.name }} ({{ net.chainId }}): - {{ predictedAddresses[net.chainId] || '—' }} - -
  • -
- Адреса вычисляются автоматически при выборе сетей. -
+ - -
-

🧩 Ключи блокчейн-сканов (опционально для авто-верификации)

-
-
- -
- - - -
-
-
-
- -
-
+
@@ -752,6 +724,8 @@ 📍 Адрес кошелька: {{ keyValidation.unified.address.substring(0, 10) }}...{{ keyValidation.unified.address.substring(keyValidation.unified.address.length - 8) }}
+ +
💰 Требуемый баланс: ~${{ totalDeployCost.toFixed(2) }}
@@ -961,10 +935,11 @@ const predictedAddress = ref(''); const predictedAddresses = reactive({}); // { chainId: address } const isPredicting = ref(false); -// Ключи блокчейн-сканов (локально) -const explorerApiKeys = reactive({}); // { [chainId]: apiKey } -const explorerKeyVisibility = reactive({}); -const persistExplorerKeys = ref(false); +// Ключ блокчейн-скана (единый Etherscan V2) +// Единый ключ Etherscan V2 и авто-верификация +const etherscanApiKey = ref(''); +const unifiedScanKeyVisible = ref(false); +const autoVerifyAfterDeploy = ref(true); // Состояние для приватных ключей const useSameKeyForAllChains = ref(true); @@ -1020,32 +995,11 @@ const hasSelectedNetworks = computed(() => { return selectedNetworks.value.length > 0; }); -// Инициализация полей ключей при смене выбранных сетей +// Инициализация при смене выбранных сетей watch(selectedNetworkDetails, (nets) => { - nets.forEach(n => { - if (!(n.chainId in explorerKeyVisibility)) explorerKeyVisibility[n.chainId] = false; - if (persistExplorerKeys.value) { - const saved = localStorage.getItem(`scan_key_${n.chainId}`); - if (saved && !explorerApiKeys[n.chainId]) explorerApiKeys[n.chainId] = saved; - } - }); if (nets && nets.length > 0) predictAddresses(); }, { immediate: true }); -watch(persistExplorerKeys, (val) => { - if (!val) return; - Object.entries(explorerApiKeys).forEach(([chainId, key]) => { - if (key) localStorage.setItem(`scan_key_${chainId}`, key); - }); -}); - -function clearExplorerKeys() { - Object.keys(explorerApiKeys).forEach((k) => explorerApiKeys[k] = ''); - Object.keys(localStorage) - .filter(k => k.startsWith('scan_key_')) - .forEach(k => localStorage.removeItem(k)); -} - // Предсказание адресов (упрощенно через бэкенд) async function predictAddresses() { try { @@ -1425,7 +1379,11 @@ const saveFormData = () => { privateKeys: { ...privateKeys }, privateKeyVisibility: { ...privateKeyVisibility }, keyValidation: { ...keyValidation }, - showUnifiedKey: showUnifiedKey.value + showUnifiedKey: showUnifiedKey.value, + // Ключи сканов/автоверификация + etherscanApiKey: etherscanApiKey.value, + autoVerifyAfterDeploy: autoVerifyAfterDeploy.value, + unifiedScanKeyVisible: unifiedScanKeyVisible.value }; localStorage.setItem(STORAGE_KEY, JSON.stringify(dataToSave)); console.log('[DleDeployForm] Данные формы сохранены в localStorage'); @@ -1496,6 +1454,11 @@ const loadFormData = () => { Object.assign(keyValidation, parsedData.keyValidation || {}); showUnifiedKey.value = parsedData.showUnifiedKey || false; + // Восстанавливаем ключи сканов/автопараметры + etherscanApiKey.value = parsedData.etherscanApiKey || ''; + autoVerifyAfterDeploy.value = !!parsedData.autoVerifyAfterDeploy; + unifiedScanKeyVisible.value = !!parsedData.unifiedScanKeyVisible; + console.log('[DleDeployForm] Данные формы восстановлены из localStorage'); console.log('[DleDeployForm] Coordinates loaded:', dleSettings.coordinates); return true; @@ -2218,6 +2181,14 @@ watch([selectedOkvedLevel1, selectedOkvedLevel2, postalCodeInput], () => { }, 100); }); +// Сохраняем Etherscan API ключ и флаг авто-верификации при изменении +watch(etherscanApiKey, () => { + saveFormData(); +}); +watch(autoVerifyAfterDeploy, () => { + saveFormData(); +}); + // Watcher для координат watch(() => dleSettings.coordinates, (newCoordinates) => { console.log('[Coordinates Watcher] Coordinates changed:', newCoordinates); @@ -2424,10 +2395,34 @@ const deploySmartContracts = async () => { // Приватный ключ для деплоя privateKey: unifiedPrivateKey.value, - explorerApiKeys: explorerApiKeys + // Верификация через Etherscan V2 + etherscanApiKey: etherscanApiKey.value, + autoVerifyAfterDeploy: autoVerifyAfterDeploy.value }; console.log('Данные для деплоя DLE:', deployData); + + // Предварительная проверка балансов во всех сетях + deployProgress.value = 20; + deployStatus.value = 'Проверка баланса во всех выбранных сетях...'; + try { + const pre = await axios.post('/dle-v2/precheck', { + supportedChainIds: deployData.supportedChainIds, + privateKey: deployData.privateKey + }); + const preData = pre.data?.data; + if (pre.data?.success && preData) { + const lacks = (preData.insufficient || []); + if (lacks.length > 0) { + const lines = (preData.balances || []).map(b => `- Chain ${b.chainId}: ${b.balanceEth} ETH${b.ok ? '' : ' (недостаточно)'}`); + alert('Недостаточно средств в некоторых сетях:\n' + lines.join('\n')); + showDeployProgress.value = false; + return; + } + } + } catch (e) { + // Если precheck недоступен, не блокируем — продолжаем + } deployProgress.value = 30; deployStatus.value = 'Отправка данных на сервер...'; @@ -2443,7 +2438,7 @@ const deploySmartContracts = async () => { deployStatus.value = '✅ DLE успешно развернут!'; // Сохраняем адрес контракта - dleSettings.predictedAddress = response.data.data?.contractAddress || 'Адрес будет доступен после деплоя'; + dleSettings.predictedAddress = response.data.data?.dleAddress || 'Адрес будет доступен после деплоя'; // Небольшая задержка для показа успешного завершения setTimeout(() => { @@ -2451,12 +2446,6 @@ const deploySmartContracts = async () => { // Перенаправляем на главную страницу управления router.push('/management'); }, 2000); - if (!persistExplorerKeys.value) { - Object.keys(explorerApiKeys).forEach((k) => explorerApiKeys[k] = ''); - Object.keys(localStorage) - .filter(k => k.startsWith('scan_key_')) - .forEach(k => localStorage.removeItem(k)); - } } else { showDeployProgress.value = false; diff --git a/frontend/src/views/settings/RpcProvidersSettings.vue b/frontend/src/views/settings/RpcProvidersSettings.vue index 0b18892..3d361c0 100644 --- a/frontend/src/views/settings/RpcProvidersSettings.vue +++ b/frontend/src/views/settings/RpcProvidersSettings.vue @@ -98,7 +98,7 @@ async function removeRpc(index) { if (!rpc) return; if (!confirm(`Удалить RPC для сети ${rpc.networkId}?`)) return; try { - await api.delete(`/api/settings/rpc/${rpc.networkId}`); + await api.delete(`/settings/rpc/${rpc.networkId}`); emit('update'); } catch (e) { alert('Ошибка при удалении RPC: ' + (e.response?.data?.error || e.message)); diff --git a/remove-unencrypted-columns.sh b/remove-unencrypted-columns.sh deleted file mode 100755 index 47bcaab..0000000 --- a/remove-unencrypted-columns.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -# Скрипт для удаления незашифрованных колонок -# ВНИМАНИЕ: Это необратимая операция! -# Использование: ./remove-unencrypted-columns.sh - -echo "⚠️ ВНИМАНИЕ: Это удалит все незашифрованные колонки!" -echo "Убедитесь, что шифрование работает корректно!" -read -p "Продолжить? (y/N): " -n 1 -r -echo -if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "❌ Операция отменена" - exit 1 -fi - -# Получаем список всех таблиц -TABLES=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " -SELECT table_name -FROM information_schema.tables -WHERE table_schema = 'public' -AND table_type = 'BASE TABLE' -ORDER BY table_name;") - -# Удаляем незашифрованные колонки -echo "$TABLES" | while read -r table_name; do - if [ -n "$table_name" ]; then - echo "🗑️ Удаление незашифрованных колонок в таблице: $table_name" - - # Получаем незашифрованные колонки - unencrypted_columns=$(docker exec dapp-postgres psql -U dapp_user -d dapp_db -t -c " - SELECT column_name - FROM information_schema.columns - WHERE table_name = '$table_name' - AND table_schema = 'public' - AND data_type IN ('text', 'varchar', 'character varying', 'json', 'jsonb') - AND column_name NOT LIKE '%_encrypted' - AND column_name NOT IN ('created_at', 'updated_at', 'id') - ORDER BY ordinal_position;") - - echo "$unencrypted_columns" | while read -r column_name; do - if [ -n "$column_name" ]; then - echo " 🗑️ Удаление колонки: $column_name" - docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " - ALTER TABLE $table_name DROP COLUMN IF EXISTS $column_name;" - fi - done - fi -done - -echo "✅ Незашифрованные колонки удалены!" diff --git a/scripts/internal/db/db_init_helper.sh b/scripts/internal/db/db_init_helper.sh new file mode 100755 index 0000000..26c5d5c --- /dev/null +++ b/scripts/internal/db/db_init_helper.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +if ! docker exec dapp-postgres pg_isready -U dapp_user -d dapp_db > /dev/null 2>&1; then + exit 1 +fi + +if [ ! -f "./ssl/keys/full_db_encryption.key" ]; then + exit 1 +fi + +ENCRYPTION_KEY=$(cat ./ssl/keys/full_db_encryption.key) +docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " +INSERT INTO rpc_providers (network_id_encrypted, rpc_url_encrypted, chain_id) +VALUES + (encrypt_text('sepolia', '$ENCRYPTION_KEY'), encrypt_text('https://eth-sepolia.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', '$ENCRYPTION_KEY'), 11155111), + (encrypt_text('holesky', '$ENCRYPTION_KEY'), encrypt_text('https://ethereum-holesky.publicnode.com', '$ENCRYPTION_KEY'), 17000) +ON CONFLICT DO NOTHING;" +docker exec dapp-postgres psql -U dapp_user -d dapp_db -c " +INSERT INTO auth_tokens (name_encrypted, address_encrypted, network_encrypted, min_balance) +VALUES + (encrypt_text('DLE', '$ENCRYPTION_KEY'), encrypt_text('0x2F2F070AA10bD3Ea14949b9953E2040a05421B17', '$ENCRYPTION_KEY'), encrypt_text('holesky', '$ENCRYPTION_KEY'), 1.0), + (encrypt_text('DLE', '$ENCRYPTION_KEY'), encrypt_text('0x2F2F070AA10bD3Ea14949b9953E2040a05421B17', '$ENCRYPTION_KEY'), encrypt_text('sepolia', '$ENCRYPTION_KEY'), 1.0) +ON CONFLICT DO NOTHING;" diff --git a/setup.sh b/setup.sh index b709dd3..b2c463e 100755 --- a/setup.sh +++ b/setup.sh @@ -63,40 +63,35 @@ print_no_git_instructions() { print_yellow "4. Запустите этот скрипт: ./setup.sh" } -# Проверка и создание .env файлов -check_env_files() { - print_blue "Проверка наличия файлов конфигурации..." +# Все настройки хранятся в зашифрованной базе данных + +# Создание ключа шифрования +create_encryption_key() { + print_blue "Проверка ключа шифрования..." - # Проверяем backend/.env - if [ ! -f backend/.env ]; then - if [ -f backend/.env.example ]; then - print_yellow "Файл backend/.env не найден. Создаю из примера..." - cp backend/.env.example backend/.env - print_green "Файл backend/.env создан. Рекомендуется настроить его вручную." + # Проверяем наличие OpenSSL + if ! command -v openssl &> /dev/null; then + print_yellow "OpenSSL не установлен. Установка..." + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + sudo apt-get update && sudo apt-get install -y openssl else - print_red "Файл backend/.env.example не найден. Невозможно создать файл конфигурации." + print_red "Пожалуйста, установите OpenSSL вручную: https://www.openssl.org/" exit 1 fi - else - print_green "Файл backend/.env уже существует." fi - # Проверяем frontend/.env - if [ ! -f frontend/.env ]; then - if [ -f frontend/.env.example ]; then - print_yellow "Файл frontend/.env не найден. Создаю из примера..." - cp frontend/.env.example frontend/.env - print_green "Файл frontend/.env создан. Рекомендуется настроить его вручную." - else - print_red "Файл frontend/.env.example не найден. Невозможно создать файл конфигурации." - exit 1 - fi - else - print_green "Файл frontend/.env уже существует." - fi + # Создаём папку для ключей + mkdir -p ./ssl/keys - print_blue "Проверка файлов конфигурации завершена." - print_yellow "ВАЖНО: По соображениям безопасности используйте свои значения для паролей и ключей в .env файлах." + # Генерируем ключ шифрования (если его нет) + if [ ! -f "./ssl/keys/full_db_encryption.key" ]; then + print_blue "🔑 Генерация ключа шифрования..." + openssl rand -base64 32 > ./ssl/keys/full_db_encryption.key + chmod 600 ./ssl/keys/full_db_encryption.key + print_green "✅ Ключ создан: ./ssl/keys/full_db_encryption.key" + else + print_green "✅ Ключ шифрования уже существует." + fi } # Предварительная загрузка образов @@ -116,6 +111,10 @@ pull_images() { done } + + + + # Запуск проекта start_project() { print_blue "Запуск проекта..." @@ -161,6 +160,61 @@ start_project() { print_green "✅ Модели предзагружены и останутся в памяти!" fi + # Добавляем токены аутентификации + print_blue "🔑 Добавление токенов аутентификации..." + ./scripts/internal/db/db_init_helper.sh 2>/dev/null || print_yellow "Токены уже добавлены или скрипт недоступен" + + # Создаём функции шифрования в PostgreSQL + print_blue "📝 Создание функций шифрования в PostgreSQL..." + docker exec dapp-postgres psql -U dapp_user -d dapp_db << 'EOF' 2>/dev/null || print_yellow "Функции шифрования уже существуют или БД не готова" +-- Создаём расширение для шифрования +CREATE EXTENSION IF NOT EXISTS pgcrypto; + +-- Функция для шифрования текста +CREATE OR REPLACE FUNCTION encrypt_text(data text, key text) +RETURNS text AS $$ +BEGIN + IF data IS NULL THEN + RETURN NULL; + END IF; + RETURN encode(encrypt_iv(data::bytea, decode(key, 'base64'), decode('000102030405060708090A0B0C0D0E0F', 'hex'), 'aes-cbc'), 'base64'); +END; +$$ LANGUAGE plpgsql; + +-- Функция для расшифровки текста +CREATE OR REPLACE FUNCTION decrypt_text(encrypted_data text, key text) +RETURNS text AS $$ +BEGIN + IF encrypted_data IS NULL THEN + RETURN NULL; + END IF; + RETURN convert_from(decrypt_iv(decode(encrypted_data, 'base64'), decode(key, 'base64'), decode('000102030405060708090A0B0C0D0E0F', 'hex'), 'aes-cbc'), 'utf8'); +END; +$$ LANGUAGE plpgsql; + +-- Функция для шифрования JSON +CREATE OR REPLACE FUNCTION encrypt_json(data jsonb, key text) +RETURNS text AS $$ +BEGIN + IF data IS NULL THEN + RETURN NULL; + END IF; + RETURN encode(encrypt_iv(data::text::bytea, decode(key, 'base64'), decode('000102030405060708090A0B0C0D0E0F', 'hex'), 'aes-cbc'), 'base64'); +END; +$$ LANGUAGE plpgsql; + +-- Функция для расшифровки JSON +CREATE OR REPLACE FUNCTION decrypt_json(encrypted_data text, key text) +RETURNS jsonb AS $$ +BEGIN + IF encrypted_data IS NULL THEN + RETURN NULL; + END IF; + RETURN convert_from(decrypt_iv(decode(encrypted_data, 'base64'), decode(key, 'base64'), decode('000102030405060708090A0B0C0D0E0F', 'hex'), 'aes-cbc'), 'utf8')::jsonb; +END; +$$ LANGUAGE plpgsql; +EOF + print_green "----------------------------------------" print_green "Проект Digital_Legal_Entity(DLE) доступен по адресам:" print_green "Frontend: http://localhost:5173" @@ -168,6 +222,9 @@ start_project() { print_green "Ollama API: http://localhost:11434" print_green "PostgreSQL: localhost:5432" print_green "----------------------------------------" + print_green "🔐 Ключ шифрования: ./ssl/keys/full_db_encryption.key" + print_green "📋 Все настройки хранятся в зашифрованной базе данных" + print_green "----------------------------------------" print_green "ИИ-ассистент готов к работе!" print_green "----------------------------------------" else @@ -188,7 +245,7 @@ main() { print_no_git_instructions check_docker - check_env_files + create_encryption_key pull_images start_project }