diff --git a/external/abi/set/CustomOracleNavIssuanceModule.json b/external/abi/set/CustomOracleNavIssuanceModule.json new file mode 100644 index 000000000..965aba3a0 --- /dev/null +++ b/external/abi/set/CustomOracleNavIssuanceModule.json @@ -0,0 +1,875 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "CustomOracleNavIssuanceModule", + "sourceName": "contracts/protocol/modules/v1/CustomOracleNAVIssuanceModule.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IController", + "name": "_controller", + "type": "address" + }, + { + "internalType": "contract IWETH", + "name": "_weth", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientEdited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newManagerFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "ManagerFeeEdited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newPremium", + "type": "uint256" + } + ], + "name": "PremiumEdited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_newReserveAsset", + "type": "address" + } + ], + "name": "ReserveAssetAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_removedReserveAsset", + "type": "address" + } + ], + "name": "ReserveAssetRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_issuer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_hookContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_setTokenQuantity", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_managerFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_premium", + "type": "uint256" + } + ], + "name": "SetTokenNAVIssued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_hookContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_setTokenQuantity", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_managerFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_premium", + "type": "uint256" + } + ], + "name": "SetTokenNAVRedeemed", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + } + ], + "name": "addReserveAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_managerFeeRecipient", + "type": "address" + } + ], + "name": "editFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managerFeePercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_managerFeeIndex", + "type": "uint256" + } + ], + "name": "editManagerFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_premiumPercentage", + "type": "uint256" + } + ], + "name": "editPremium", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_setTokenQuantity", + "type": "uint256" + } + ], + "name": "getExpectedReserveRedeemQuantity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_reserveAssetQuantity", + "type": "uint256" + } + ], + "name": "getExpectedSetTokenIssueQuantity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_reserveAssetQuantity", + "type": "uint256" + } + ], + "name": "getIssuePremium", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managerFeeIndex", + "type": "uint256" + } + ], + "name": "getManagerFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_setTokenQuantity", + "type": "uint256" + } + ], + "name": "getRedeemPremium", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + } + ], + "name": "getReserveAssets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract INAVIssuanceHook", + "name": "managerIssuanceHook", + "type": "address" + }, + { + "internalType": "contract INAVIssuanceHook", + "name": "managerRedemptionHook", + "type": "address" + }, + { + "internalType": "contract ISetValuer", + "name": "setValuer", + "type": "address" + }, + { + "internalType": "address[]", + "name": "reserveAssets", + "type": "address[]" + }, + { + "internalType": "address", + "name": "feeRecipient", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "managerFees", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "maxManagerFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "premiumPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPremiumPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSetTokenSupply", + "type": "uint256" + } + ], + "internalType": "struct CustomOracleNavIssuanceModule.NAVIssuanceSettings", + "name": "_navIssuanceSettings", + "type": "tuple" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_reserveAssetQuantity", + "type": "uint256" + } + ], + "name": "isIssueValid", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_setTokenQuantity", + "type": "uint256" + } + ], + "name": "isRedeemValid", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isReserveAsset", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_reserveAssetQuantity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minSetTokenReceiveQuantity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "issue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_minSetTokenReceiveQuantity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "issueWithEther", + "outputs": [], + "stateMutability": "payable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "", + "type": "address" + } + ], + "name": "navIssuanceSettings", + "outputs": [ + { + "internalType": "contract INAVIssuanceHook", + "name": "managerIssuanceHook", + "type": "address" + }, + { + "internalType": "contract INAVIssuanceHook", + "name": "managerRedemptionHook", + "type": "address" + }, + { + "internalType": "contract ISetValuer", + "name": "setValuer", + "type": "address" + }, + { + "internalType": "address", + "name": "feeRecipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxManagerFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "premiumPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPremiumPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSetTokenSupply", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_setTokenQuantity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minReserveReceiveQuantity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_setTokenQuantity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minReserveReceiveQuantity", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "_to", + "type": "address" + } + ], + "name": "redeemIntoEther", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "removeModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_reserveAsset", + "type": "address" + } + ], + "name": "removeReserveAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162004f1f38038062004f1f83398101604081905262000034916200006f565b600080546001600160a01b0319166001600160a01b0393909316929092179091556001805560601b6001600160601b031916608052620000c6565b6000806040838503121562000082578182fd5b82516200008f81620000ad565b6020840151909250620000a281620000ad565b809150509250929050565b6001600160a01b0381168114620000c357600080fd5b50565b60805160601c614df56200012a6000398061047252806104ea5280610515528061054a528061058c52806108ae528061141b528061145a5280611502528061154b52806115f1528061161c5280611a0d5280611aa15280611c065250614df56000f3fe6080604052600436106101445760003560e01c80637f977948116100b6578063b36f7e8c1161006f578063b36f7e8c1461038c578063d5f8394a146103ac578063df3fa714146103cc578063ee673ac4146103ec578063f529c18a146101fb578063f77c4791146104205761014b565b80637f977948146102d7578063847ef08d146102f757806391819fb31461030c5780639c5ad2831461032c5780639f6f6ba91461034c578063add7745a1461036c5761014b565b80632f879fa3116101085780632f879fa3146101fb57806330b305f91461021b5780633fc8cef31461023b5780634b79da0a1461025d57806364b2dc7a1461028a5780636ff7f6da146102b75761014b565b806302c619d01461015057806304f1b57114610165578063080b16f81461019b5780630e3af8ad146101bb578063281d0115146101db5761014b565b3661014b57005b600080fd5b61016361015e366004614024565b610435565b005b34801561017157600080fd5b50610185610180366004613ff9565b6105bd565b6040516101929190614338565b60405180910390f35b3480156101a757600080fd5b506101636101b6366004613e18565b6105f0565b3480156101c757600080fd5b506101636101d6366004613ff9565b610690565b3480156101e757600080fd5b506101636101f6366004613e18565b610723565b34801561020757600080fd5b50610185610216366004613e50565b610807565b34801561022757600080fd5b50610163610236366004613e90565b61081e565b34801561024757600080fd5b506102506108ac565b6040516101929190614163565b34801561026957600080fd5b5061027d610278366004613dfc565b6108d0565b604051610192919061421f565b34801561029657600080fd5b506102aa6102a5366004613e18565b610949565b604051610192919061426c565b3480156102c357600080fd5b506101856102d2366004613e50565b610969565b3480156102e357600080fd5b506101856102f2366004613e50565b610997565b34801561030357600080fd5b50610163610a39565b34801561031857600080fd5b50610163610327366004613e18565b610b57565b34801561033857600080fd5b506102aa610347366004613e50565b610cc9565b34801561035857600080fd5b50610163610367366004613e90565b610e81565b34801561037857600080fd5b506102aa610387366004613e50565b610f84565b34801561039857600080fd5b506101636103a7366004613eee565b61105e565b3480156103b857600080fd5b506101636103c7366004614099565b6113e3565b3480156103d857600080fd5b506101636103e7366004614065565b61164e565b3480156103f857600080fd5b5061040c610407366004613dfc565b611714565b604051610192989796959493929190614277565b34801561042c57600080fd5b50610250611769565b600260015414156104615760405162461bcd60e51b815260040161045890614cf2565b60405180910390fd5b60026001558261047081611778565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156104cb57600080fd5b505af11580156104df573d6000803e3d6000fd5b505050505061050f847f0000000000000000000000000000000000000000000000000000000000000000346117a0565b61053c847f000000000000000000000000000000000000000000000000000000000000000034338661180a565b610544613a70565b61056f857f00000000000000000000000000000000000000000000000000000000000000003461189a565b905061057c85858361198e565b61058685826119f1565b6105b2857f00000000000000000000000000000000000000000000000000000000000000008584611c95565b505060018055505050565b6001600160a01b0382166000908152600260208190526040822060050190839081106105e557fe5b015490505b92915050565b816105fa81611de2565b6001600160a01b0382166106205760405162461bcd60e51b8152600401610458906145d7565b6001600160a01b038381166000818152600260205260409081902060040180546001600160a01b0319169386169390931790925590517fff78699124ce6ab1e48255152542b253d1e5c0fc925308a48852e674777ace3590610683908590614163565b60405180910390a2505050565b8161069a81611de2565b6001600160a01b0383166000908152600260205260409020600901548211156106d55760405162461bcd60e51b8152600401610458906147d1565b6001600160a01b03831660008181526002602052604090819020600801849055517fd0db665d5987480b1c4e28f4484b1a9fabff141ffcb5a9ff9f384e4672155c0590610683908590614338565b8161072d81611de2565b6001600160a01b0380841660009081526003602090815260408083209386168352929052205460ff16156107735760405162461bcd60e51b8152600401610458906146ae565b6001600160a01b03838116600081815260026020908152604080832060039081018054600180820183559186528486200180546001600160a01b031916978a1697881790558585529083528184209584529490915290819020805460ff191690931790925590517f94257d51a6470b587cb1ae3068fee4bce93eff4d149a98bd05aee37ae491148790610683908590614163565b6000610814848484611e08565b90505b9392505050565b600260015414156108415760405162461bcd60e51b815260040161045890614cf2565b60026001558461085081611778565b61085b8686866117a0565b610868868686338661180a565b610870613a70565b61087b87878761189a565b905061088887858361198e565b610893878783611e28565b61089f87878584611c95565b5050600180555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03811660009081526002602090815260409182902060030180548351818402810184019094528084526060939283018282801561093d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161091f575b50505050509050919050565b600360209081526000928352604080842090915290825290205460ff1681565b600080610977858585611f13565b9050600061098b8683600160036001612083565b98975050505050505050565b6000806109aa8584600060026000612083565b925050506000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109e957600080fd5b505afa1580156109fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2191906140e2565b9050610a2f868684846120fa565b9695505050505050565b3360005b6001600160a01b038216600090815260026020526040902060030154811015610ac8576001600160a01b038216600090815260036020818152604080842060029092528320909101805491929184908110610a9457fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020805460ff19169055600101610a3d565b506001600160a01b0381166000908152600260208190526040822080546001600160a01b0319908116825560018201805482169055918101805490921690915590610b166003830182613abc565b6004820180546001600160a01b0319169055610b36600583016000613ada565b506000600782018190556008820181905560098201819055600a9091015550565b81610b6181611de2565b6001600160a01b0380841660009081526003602090815260408083209386168352929052205460ff16610ba65760405162461bcd60e51b81526004016104589061461a565b610c398260026000866001600160a01b03166001600160a01b03168152602001908152602001600020600301805480602002602001604051908101604052809291908181526020018280548015610c2657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c08575b50505050506122ac90919063ffffffff16565b6001600160a01b03841660009081526002602090815260409091208251610c6a936003909201929190910190613ae8565b506001600160a01b0380841660008181526003602090815260408083209487168352939052829020805460ff1916905590517f3c59157886f089a91f7813e86300f9f9b36289e41e7c09c70f9cc208b810cd9490610683908590614163565b600080846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d0557600080fd5b505afa158015610d19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3d91906140e2565b9050821580610d7257506001600160a01b0380861660009081526003602090815260408083209388168352929052205460ff16155b80610da757506001600160a01b0385166000908152600260205260409020600a0154610da4908463ffffffff6122f416565b81105b15610db6576000915050610817565b6000610dc3868686611f13565b90506000610dd78783600160036001612083565b925050506000610e61886001600160a01b03166366cb8d2f896040518263ffffffff1660e01b8152600401610e0c9190614163565b60206040518083038186803b158015610e2457600080fd5b505afa158015610e38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5c91906140e2565b612319565b905081610e74828663ffffffff61233f16565b1015945050505050610817565b60026001541415610ea45760405162461bcd60e51b815260040161045890614cf2565b600260015584610eb381611778565b610ebe8686866117a0565b610eca86853385612369565b610ed2613a70565b610edd8787876123e0565b9050610eea8785836124c3565b604051632770a7eb60e21b81526001600160a01b03881690639dc29fac90610f1890339089906004016141bb565b600060405180830381600087803b158015610f3257600080fd5b505af1158015610f46573d6000803e3d6000fd5b5050506060820151610f6d91506001600160a01b038916908890869063ffffffff61252616565b610f7887878361266e565b61089f878785846126bd565b600080846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc057600080fd5b505afa158015610fd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff891906140e2565b9050821580159061102e57506001600160a01b0380861660009081526003602090815260408083209388168352929052205460ff165b801561105557506001600160a01b0385166000908152600260205260409020600a01548110155b95945050505050565b813361106a82826127ab565b83611074816127d1565b6000846060015151116110995760405162461bcd60e51b8152600401610458906146e5565b6110a1612892565b8460c00151106110c35760405162461bcd60e51b815260040161045890614c77565b6110cb612892565b846101000151106110ee5760405162461bcd60e51b8152600401610458906148c7565b60c084015160a08501515111156111175760405162461bcd60e51b815260040161045890614a59565b60c084015160a08501516020015111156111435760405162461bcd60e51b81526004016104589061458f565b8361010001518460e00151111561116c5760405162461bcd60e51b815260040161045890614521565b60808401516001600160a01b03166111965760405162461bcd60e51b815260040161045890614aa0565b6000846101200151116111bb5760405162461bcd60e51b81526004016104589061445f565b60005b8460600151518110156112a3576001600160a01b038616600090815260036020526040812060608701518051919291849081106111f757fe5b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff161561123b5760405162461bcd60e51b815260040161045890614963565b6001600160a01b03861660009081526003602052604081206060870151805160019391908590811061126957fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff19169115159190911790556001016111be565b506001600160a01b03808616600090815260026020818152604092839020885181549086166001600160a01b0319918216178255828a015160018301805491881691831691909117905593890151928101805493909516929093169190911790925560608601518051879361131f926003850192910190613ae8565b5060808201516004820180546001600160a01b0319166001600160a01b0390921691909117905560a082015161135b9060058301906002613b49565b5060c0820151816007015560e08201518160080155610100820151816009015561012082015181600a0155905050846001600160a01b0316630ffe0f1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113c457600080fd5b505af11580156113d8573d6000803e3d6000fd5b505050505050505050565b600260015414156114065760405162461bcd60e51b815260040161045890614cf2565b60026001558361141581611778565b611440857f0000000000000000000000000000000000000000000000000000000000000000866117a0565b61144c85853385612369565b611454613a70565b61147f867f0000000000000000000000000000000000000000000000000000000000000000876123e0565b905061148c8685836124c3565b604051632770a7eb60e21b81526001600160a01b03871690639dc29fac906114ba90339089906004016141bb565b600060405180830381600087803b1580156114d457600080fd5b505af11580156114e8573d6000803e3d6000fd5b505050606082015161152f91506001600160a01b038816907f000000000000000000000000000000000000000000000000000000000000000090309063ffffffff61252616565b6060810151604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691632e1a7d4d9161157f9190600401614338565b600060405180830381600087803b15801561159957600080fd5b505af11580156115ad573d6000803e3d6000fd5b5050505060608101516040516001600160a01b038516916108fc811502916000818181858888f193505050501580156115ea573d6000803e3d6000fd5b50611616867f00000000000000000000000000000000000000000000000000000000000000008361266e565b611642867f000000000000000000000000000000000000000000000000000000000000000085846126bd565b50506001805550505050565b8261165881611de2565b6001600160a01b0384166000908152600260205260409020600701548311156116935760405162461bcd60e51b815260040161045890614be0565b8260026000866001600160a01b03166001600160a01b0316815260200190815260200160002060050183600281106116c757fe5b01556040516001600160a01b038516907f4e913bee7cf10ece89b3c5593df3898d1a324864d38052df88792a7d87a17488906117069086908690614d29565b60405180910390a250505050565b600260208190526000918252604090912080546001820154928201546004830154600784015460088501546009860154600a909601546001600160a01b03958616978616969486169590931693919290919088565b6000546001600160a01b031681565b6117818161289f565b61179d5760405162461bcd60e51b815260040161045890614417565b50565b600081116117c05760405162461bcd60e51b8152600401610458906143e9565b6001600160a01b0380841660009081526003602090815260408083209386168352929052205460ff166118055760405162461bcd60e51b81526004016104589061481a565b505050565b6001600160a01b0380861660009081526002602052604090205416801561189257604051633ed0b9fb60e21b81526001600160a01b0382169063fb42e7ec9061185f90899089908990899089906004016142db565b600060405180830381600087803b15801561187957600080fd5b505af115801561188d573d6000803e3d6000fd5b505050505b505050505050565b6118a2613a70565b6118aa613a70565b846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156118e357600080fd5b505afa1580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b91906140e2565b60a082015282815261193285846000600281612083565b606084018190526040840191909152602083019190915260a082015161195c9187918791906120fa565b608082015261196b85826129a3565b60e083015260c0820152611980858583612a7b565b610100820152949350505050565b6001600160a01b0383166000908152600260205260409020600a015460a082015110156119cd5760405162461bcd60e51b81526004016104589061472a565b81816080015110156118055760405162461bcd60e51b8152600401610458906144a9565b606081015160405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91611a429186916004016141bb565b602060405180830381600087803b158015611a5c57600080fd5b505af1158015611a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a949190613d50565b50602081015115611bc9577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6000809054906101000a90046001600160a01b03166001600160a01b031663469048406040518163ffffffff1660e01b815260040160206040518083038186803b158015611b1b57600080fd5b505afa158015611b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b539190613c98565b83602001516040518363ffffffff1660e01b8152600401611b759291906141bb565b602060405180830381600087803b158015611b8f57600080fd5b505af1158015611ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc79190613d50565b505b604081015115611c91576001600160a01b038281166000908152600260205260409081902060049081015484830151925163a9059cbb60e01b81527f000000000000000000000000000000000000000000000000000000000000000085169463a9059cbb94611c3f9493909116929091016141bb565b602060405180830381600087803b158015611c5957600080fd5b505af1158015611c6d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118059190613d50565b5050565b60e081015160405163c2de0e9d60e01b81526001600160a01b0386169163c2de0e9d91611cc59190600401614338565b600060405180830381600087803b158015611cdf57600080fd5b505af1158015611cf3573d6000803e3d6000fd5b505050610100820151611d1991506001600160a01b03861690859063ffffffff612ae916565b60808101516040516340c10f1960e01b81526001600160a01b038616916340c10f1991611d4a9186916004016141bb565b600060405180830381600087803b158015611d6457600080fd5b505af1158015611d78573d6000803e3d6000fd5b5050506001600160a01b03808616600081815260026020908152604091829020546080870151878401519288015193519496507fab151ef72553d84db96b5656139e68d5e348f8273d15b1724db8f3c09832d80e956117069533958b958d95909316939291614177565b611dec8133612c67565b6117785760405162461bcd60e51b815260040161045890614ba9565b50506001600160a01b031660009081526002602052604090206008015490565b611e388233858460600151612cf5565b602081015115611ed657611ed682336000809054906101000a90046001600160a01b03166001600160a01b031663469048406040518163ffffffff1660e01b815260040160206040518083038186803b158015611e9457600080fd5b505afa158015611ea8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ecc9190613c98565b8460200151612cf5565b604081015115611805576001600160a01b038084166000908152600260205260409081902060040154908301516118059285923392911690612cf5565b600080611f1f85612d01565b6001600160a01b0316636101c54086866040518363ffffffff1660e01b8152600401611f4c9291906142c1565b60206040518083038186803b158015611f6457600080fd5b505afa158015611f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9c91906140e2565b90506000611fb0848363ffffffff61233f16565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611fed57600080fd5b505afa158015612001573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202591906140fa565b60ff169050600061204083600a84900a63ffffffff61233f16565b9050600061204f898989611e08565b90506000612063838363ffffffff612d4216565b9050612075838263ffffffff612d8116565b9a9950505050505050505050565b60008060008060006120978a898989612dc3565b909250905060006120ae838b63ffffffff61233f16565b905060006120c2838c63ffffffff61233f16565b905060006120e6826120da8e8663ffffffff612d8116565b9063ffffffff612d8116565b929d919c50919a5098505050505050505050565b600080612108868686611e08565b9050600061211c858363ffffffff61233f16565b9050600061212988612d01565b6001600160a01b0316636101c54089896040518363ffffffff1660e01b81526004016121569291906142c1565b60206040518083038186803b15801561216e57600080fd5b505afa158015612182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a691906140e2565b90506000876001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156121e357600080fd5b505afa1580156121f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221b91906140fa565b60ff169050600061223688600a84900a63ffffffff612f5916565b9050600061225e600a84900a6122528b8863ffffffff612d8116565b9063ffffffff612f5916565b90506000612286826120da8561227a8d8a63ffffffff61233f16565b9063ffffffff6122f416565b905061229c81612252848c63ffffffff61233f16565b9c9b505050505050505050505050565b60606000806122bb8585612f77565b91509150806122dc5760405162461bcd60e51b815260040161045890614354565b60606122e88684612fda565b5093506105ea92505050565b6000828201838110156108175760405162461bcd60e51b8152600401610458906144ea565b60008082121561233b5760405162461bcd60e51b815260040161045890614851565b5090565b6000610817670de0b6b3a764000061235d858563ffffffff61310916565b9063ffffffff61314316565b6001600160a01b038085166000908152600260205260409020600101541680156123d957604051639b19c2bf60e01b81526001600160a01b03821690639b19c2bf906123bf90889088908890889060040161430d565b600060405180830381600087803b1580156113c457600080fd5b5050505050565b6123e8613a70565b6123f0613a70565b60808101839052612402858585611f13565b8082526124159086906001600381612083565b606084015260408084019190915260208084019290925280516318160ddd60e01b815290516001600160a01b038816926318160ddd9260048082019391829003018186803b15801561246657600080fd5b505afa15801561247a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249e91906140e2565b60a08201526124ae858483613185565b60e083015260c0820152611980858583613208565b6001600160a01b0383166000908152600260205260409020600a015460c082015110156125025760405162461bcd60e51b815260040161045890614651565b81816060015110156118055760405162461bcd60e51b815260040161045890614780565b8015612668576040516370a0823160e01b81526000906001600160a01b038516906370a082319061255b908890600401614163565b60206040518083038186803b15801561257357600080fd5b505afa158015612587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ab91906140e2565b90506125b9858585856132c2565b6040516370a0823160e01b81526000906001600160a01b038616906370a08231906125e8908990600401614163565b60206040518083038186803b15801561260057600080fd5b505afa158015612614573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263891906140e2565b905061264a828463ffffffff612d8116565b81146118925760405162461bcd60e51b815260040161045890614a22565b50505050565b61267d838383602001516133cc565b604081015115611805576001600160a01b03808416600081815260026020526040908190206004015490840151611805938692169063ffffffff61252616565b60e081015160405163c2de0e9d60e01b81526001600160a01b0386169163c2de0e9d916126ed9190600401614338565b600060405180830381600087803b15801561270757600080fd5b505af115801561271b573d6000803e3d6000fd5b50505061010082015161274191506001600160a01b03861690859063ffffffff612ae916565b6001600160a01b038085166000818152600260209081526040918290206001015460808601518684015192870151935194957f76608da3459f30443b27df4954c2ee5953695a78cf2327545bc5992eca749f4f956117069533958b958d9594169392909190614177565b6127b58282612c67565b611c915760405162461bcd60e51b815260040161045890614ba9565b600054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec90612801908490600401614163565b60206040518083038186803b15801561281957600080fd5b505afa15801561282d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128519190613d50565b61286d5760405162461bcd60e51b815260040161045890614b66565b61287681613473565b61179d5760405162461bcd60e51b815260040161045890614558565b670de0b6b3a76400005b90565b60008054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec906128d0908590600401614163565b60206040518083038186803b1580156128e857600080fd5b505afa1580156128fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129209190613d50565b80156105ea57506040516335fc6c9f60e21b81526001600160a01b0383169063d7f1b27c90612953903090600401614163565b60206040518083038186803b15801561296b57600080fd5b505afa15801561297f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea9190613d50565b60008060006129c38460a0015185608001516122f490919063ffffffff16565b90506000612a6c6129d3836134a2565b612a606129e38860a001516134a2565b896001600160a01b0316635230c3966040518163ffffffff1660e01b815260040160206040518083038186803b158015612a1c57600080fd5b505afa158015612a30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5491906140e2565b9063ffffffff6134c716565b9063ffffffff61353216565b919350909150505b9250929050565b600080612aad856001600160a01b03166366cb8d2f866040518263ffffffff1660e01b8152600401610e0c9190614163565b90506000612ad0846060015161227a8660a001518561233f90919063ffffffff16565b9050610a2f8460c0015182612f5990919063ffffffff16565b6000612af58484613596565b905080158015612b055750600082115b15612b7c57612b14848461361d565b612b77576040516304e3532760e41b81526001600160a01b03851690634e35327090612b44908690600401614163565b600060405180830381600087803b158015612b5e57600080fd5b505af1158015612b72573d6000803e3d6000fd5b505050505b612bf9565b808015612b87575081155b15612bf957612b96848461361d565b612bf957604051636f86c89760e01b81526001600160a01b03851690636f86c89790612bc6908690600401614163565b600060405180830381600087803b158015612be057600080fd5b505af1158015612bf4573d6000803e3d6000fd5b505050505b836001600160a01b0316632ba57d1784612c12856134a2565b6040518363ffffffff1660e01b8152600401612c2f9291906141bb565b600060405180830381600087803b158015612c4957600080fd5b505af1158015612c5d573d6000803e3d6000fd5b5050505050505050565b6000816001600160a01b0316836001600160a01b031663481c6a756040518163ffffffff1660e01b815260040160206040518083038186803b158015612cac57600080fd5b505afa158015612cc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce49190613c98565b6001600160a01b0316149392505050565b612668848484846136a9565b6001600160a01b038082166000908152600260208190526040822001549091168015612d2d5780610817565b600054610817906001600160a01b03166137cd565b6000821580612d4f575081155b15612d5c575060006105ea565b610817600161227a670de0b6b3a764000061235d836120da898963ffffffff61310916565b600061081783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061384d565b6000805460405163792aa04f60e01b8152829182916001600160a01b039091169063792aa04f90612dfa90309089906004016141bb565b60206040518083038186803b158015612e1257600080fd5b505afa158015612e26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e4a91906140e2565b6000805460405163792aa04f60e01b815292935090916001600160a01b039091169063792aa04f90612e829030908b906004016141bb565b60206040518083038186803b158015612e9a57600080fd5b505afa158015612eae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed291906140e2565b90506000600260008a6001600160a01b03166001600160a01b031681526020019081526020016000206005018660028110612f0957fe5b015490506000612f1f838363ffffffff61233f16565b90506000612f33838363ffffffff612d8116565b90506000612f47838763ffffffff6122f416565b9c919b50909950505050505050505050565b60006108178261235d85670de0b6b3a764000063ffffffff61310916565b81516000908190815b81811015612fca57846001600160a01b0316868281518110612f9e57fe5b60200260200101516001600160a01b03161415612fc257925060019150612a749050565b600101612f80565b5060001995600095509350505050565b81516060906000908084106130015760405162461bcd60e51b815260040161045890614383565b60606001820367ffffffffffffffff8111801561301d57600080fd5b50604051908082528060200260200182016040528015613047578160200160208202803683370190505b50905060005b858110156130955786818151811061306157fe5b602002602001015182828151811061307557fe5b6001600160a01b039092166020928302919091019091015260010161304d565b50600185015b828110156130e6578681815181106130af57fe5b60200260200101518260018303815181106130c657fe5b6001600160a01b039092166020928302919091019091015260010161309b565b50808686815181106130f457fe5b60200260200101519350935050509250929050565b600082613118575060006105ea565b8282028284828161312557fe5b04146108175760405162461bcd60e51b81526004016104589061499a565b600061081783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613879565b60008060006131a1858560a00151612d8190919063ffffffff16565b905060006131fa6131b1836134a2565b612a606131c18860a001516134a2565b8a6001600160a01b0316635230c3966040518163ffffffff1660e01b815260040160206040518083038186803b158015612a1c57600080fd5b919791965090945050505050565b60008061323a856001600160a01b03166366cb8d2f866040518263ffffffff1660e01b8152600401610e0c9190614163565b905060006132558460a001518361233f90919063ffffffff16565b9050600061327c856040015161227a876020015188606001516122f490919063ffffffff16565b90508082101561329e5760405162461bcd60e51b815260040161045890614914565b60c08501516132b790612252848463ffffffff612d8116565b979650505050505050565b801561266857606082826040516024016132dd9291906141bb565b60408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b179052516347b7819960e11b81529091506060906001600160a01b03871690638f6f03329061333c90889060009087906004016141f8565b600060405180830381600087803b15801561335657600080fd5b505af115801561336a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526133929190810190613d70565b80519091501561189257808060200190518101906133b09190613d50565b6118925760405162461bcd60e51b8152600401610458906143ba565b801561180557611805826000809054906101000a90046001600160a01b03166001600160a01b031663469048406040518163ffffffff1660e01b815260040160206040518083038186803b15801561342357600080fd5b505afa158015613437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061345b9190613c98565b6001600160a01b03861691908463ffffffff61252616565b6040516353bae5f760e01b81526000906001600160a01b038316906353bae5f790612953903090600401614163565b6000600160ff1b821061233b5760405162461bcd60e51b815260040161045890614b1e565b6000826134d6575060006105ea565b826000191480156134ea5750600160ff1b82145b156135075760405162461bcd60e51b8152600401610458906149db565b8282028284828161351457fe5b05146108175760405162461bcd60e51b8152600401610458906149db565b6000816135515760405162461bcd60e51b815260040161045890614cbd565b816000191480156135655750600160ff1b83145b156135825760405162461bcd60e51b815260040161045890614886565b600082848161358d57fe5b05949350505050565b600080836001600160a01b03166366cb8d2f846040518263ffffffff1660e01b81526004016135c59190614163565b60206040518083038186803b1580156135dd57600080fd5b505afa1580156135f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061361591906140e2565b139392505050565b600080836001600160a01b031663a7bdad03846040518263ffffffff1660e01b815260040161364c9190614163565b60006040518083038186803b15801561366457600080fd5b505afa158015613678573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526136a09190810190613cb4565b51119392505050565b8015612668576040516370a0823160e01b81526000906001600160a01b038616906370a08231906136de908690600401614163565b60206040518083038186803b1580156136f657600080fd5b505afa15801561370a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061372e91906140e2565b905061373c858585856138b0565b6040516370a0823160e01b81526000906001600160a01b038716906370a082319061376b908790600401614163565b60206040518083038186803b15801561378357600080fd5b505afa158015613797573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bb91906140e2565b905061264a828463ffffffff6122f416565b6040516373b2e76b60e11b81526000906001600160a01b0383169063e765ced6906137fd90600290600401614338565b60206040518083038186803b15801561381557600080fd5b505afa158015613829573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea9190613c98565b600081848411156138715760405162461bcd60e51b81526004016104589190614341565b505050900390565b6000818361389a5760405162461bcd60e51b81526004016104589190614341565b5060008385816138a657fe5b0495945050505050565b612668846323b872dd60e01b8585856040516024016138d1939291906141d4565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060613958826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139929092919063ffffffff16565b80519091501561180557808060200190518101906139769190613d50565b6118055760405162461bcd60e51b815260040161045890614c2d565b60606108148484600085856139a685613a31565b6139c25760405162461bcd60e51b815260040161045890614ae7565b60006060866001600160a01b031685876040516139df9190614147565b60006040518083038185875af1925050503d8060008114613a1c576040519150601f19603f3d011682016040523d82523d6000602084013e613a21565b606091505b50915091506132b7828286613a37565b3b151590565b60608315613a46575081610817565b825115613a565782518084602001fd5b8160405162461bcd60e51b81526004016104589190614341565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b508054600082559060005260206000209081019061179d9190613b7f565b506000815560010160009055565b828054828255906000526020600020908101928215613b3d579160200282015b82811115613b3d57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613b08565b5061233b929150613b99565b8260028101928215613b77579160200282015b82811115613b77578251825591602001919060010190613b5c565b5061233b9291505b61289c91905b8082111561233b5760008155600101613b85565b61289c91905b8082111561233b5780546001600160a01b0319168155600101613b9f565b80356105ea81614daa565b600082601f830112613bd8578081fd5b8135613beb613be682614d5e565b614d37565b818152915060208083019084810181840286018201871015613c0c57600080fd5b60005b84811015613c34578135613c2281614daa565b84529282019290820190600101613c0f565b505050505092915050565b600082601f830112613c4f578081fd5b613c596040614d37565b9050808284604085011115613c6d57600080fd5b60005b6002811015613c8f578135835260209283019290910190600101613c70565b50505092915050565b600060208284031215613ca9578081fd5b815161081781614daa565b60006020808385031215613cc6578182fd5b825167ffffffffffffffff811115613cdc578283fd5b80840185601f820112613ced578384fd5b80519150613cfd613be683614d5e565b8281528381019082850185850284018601891015613d19578687fd5b8693505b84841015613d44578051613d3081614daa565b835260019390930192918501918501613d1d565b50979650505050505050565b600060208284031215613d61578081fd5b81518015158114610817578182fd5b600060208284031215613d81578081fd5b815167ffffffffffffffff80821115613d98578283fd5b81840185601f820112613da9578384fd5b8051925081831115613db9578384fd5b613dcc601f8401601f1916602001614d37565b9150828252856020848301011115613de2578384fd5b613df3836020840160208401614d7e565b50949350505050565b600060208284031215613e0d578081fd5b813561081781614daa565b60008060408385031215613e2a578081fd5b8235613e3581614daa565b91506020830135613e4581614daa565b809150509250929050565b600080600060608486031215613e64578081fd5b8335613e6f81614daa565b92506020840135613e7f81614daa565b929592945050506040919091013590565b600080600080600060a08688031215613ea7578283fd5b8535613eb281614daa565b94506020860135613ec281614daa565b935060408601359250606086013591506080860135613ee081614daa565b809150509295509295909350565b60008060408385031215613f00578182fd5b8235613f0b81614daa565b9150602083013567ffffffffffffffff80821115613f27578283fd5b8185016101608188031215613f3a578384fd5b6101409250613f4883614d37565b613f528883613bbd565b8152613f618860208401613bbd565b6020820152613f738860408401613bbd565b6040820152606082013583811115613f89578586fd5b613f9589828501613bc8565b606083015250613fa88860808401613bbd565b6080820152613fba8860a08401613c3f565b60a082015260e082013560c082015261010092508282013560e08201526101208083013584830152848301358183015250809450505050509250929050565b6000806040838503121561400b578182fd5b823561401681614daa565b946020939093013593505050565b600080600060608486031215614038578081fd5b833561404381614daa565b925060208401359150604084013561405a81614daa565b809150509250925092565b600080600060608486031215614079578081fd5b833561408481614daa565b95602085013595506040909401359392505050565b600080600080608085870312156140ae578182fd5b84356140b981614daa565b9350602085013592506040850135915060608501356140d781614daa565b939692955090935050565b6000602082840312156140f3578081fd5b5051919050565b60006020828403121561410b578081fd5b815160ff81168114610817578182fd5b60008151808452614133816020860160208601614d7e565b601f01601f19169290920160200192915050565b60008251614159818460208701614d7e565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03978816815295871660208701529386166040860152919094166060840152608083019390935260a082019290925260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060018060a01b038516825283602083015260606040830152611055606083018461411b565b6020808252825182820181905260009190848201906040850190845b818110156142605783516001600160a01b03168352928401929184019160010161423b565b50909695505050505050565b901515815260200190565b6001600160a01b03988916815296881660208801529487166040870152929095166060850152608084015260a083019390935260c082019290925260e08101919091526101000190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0395861681529385166020850152604084019290925283166060830152909116608082015260a00190565b6001600160a01b03948516815260208101939093529083166040830152909116606082015260800190565b90815260200190565b600060208252610817602083018461411b565b60208082526015908201527420b2323932b9b9903737ba1034b71030b93930bc9760591b604082015260600190565b60208082526018908201527f496e646578206d757374206265203c2041206c656e6774680000000000000000604082015260600190565b602080825260159082015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b60208082526014908201527305175616e74697479206d757374206265203e20360641b604082015260600190565b60208082526028908201527f4d75737420626520612076616c696420616e6420696e697469616c697a65642060408201526729b2ba2a37b5b2b760c11b606082015260800190565b6020808252602a908201527f4d696e20536574546f6b656e20737570706c79206d75737420626520677265616040820152690746572207468616e20360b41b606082015260800190565b60208082526021908201527f4d7573742062652067726561746572207468616e206d696e20536574546f6b656040820152603760f91b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601d908201527f5072656d69756d206d757374206265206c657373207468616e206d6178000000604082015260600190565b6020808252601e908201527f4d7573742062652070656e64696e6720696e697469616c697a6174696f6e0000604082015260600190565b60208082526028908201527f4d616e616765722072656465656d20666565206d757374206265206c657373206040820152670e8d0c2dc40dac2f60c31b606082015260800190565b60208082526023908201527f46656520726563697069656e74206d757374206e6f742062652030206164647260408201526265737360e81b606082015260800190565b6020808252601c908201527f5265736572766520617373657420646f6573206e6f7420657869737400000000604082015260600190565b60208082526038908201527f537570706c79206d7573742062652067726561746572207468616e206d696e6960408201527f6d756d20746f20656e61626c6520726564656d7074696f6e0000000000000000606082015260800190565b6020808252601c908201527f5265736572766520617373657420616c72656164792065786973747300000000604082015260600190565b60208082526025908201527f5265736572766520617373657473206d75737420626520677265617465722074604082015264068616e20360dc1b606082015260800190565b60208082526036908201527f537570706c79206d7573742062652067726561746572207468616e206d696e696040820152756d756d20746f20656e61626c652069737375616e636560501b606082015260800190565b60208082526031908201527f4d7573742062652067726561746572207468616e206d696e20726563656976656040820152702072657365727665207175616e7469747960781b606082015260800190565b60208082526029908201527f5072656d69756d206d757374206265206c657373207468616e206d6178696d756040820152681b48185b1b1bddd95960ba1b606082015260800190565b6020808252601b908201527f4d7573742062652076616c696420726573657276652061737365740000000000604082015260600190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602d908201527f4d6178207072656d69756d2070657263656e74616765206d757374206265206c60408201526c657373207468616e203130302560981b606082015260800190565b6020808252602f908201527f4d7573742062652067726561746572207468616e20746f74616c20617661696c60408201526e18589b194818dbdb1b185d195c985b608a1b606082015260800190565b6020808252601d908201527f5265736572766520617373657473206d75737420626520756e69717565000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b6020808252601d908201527f496e76616c696420706f7374207472616e736665722062616c616e6365000000604082015260600190565b60208082526027908201527f4d616e6167657220697373756520666565206d757374206265206c65737320746040820152660d0c2dc40dac2f60cb1b606082015260800190565b60208082526027908201527f46656520526563697069656e74206d757374206265206e6f6e2d7a65726f206160408201526632323932b9b99760c91b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b60208082526023908201527f4d75737420626520636f6e74726f6c6c65722d656e61626c656420536574546f60408201526235b2b760e91b606082015260800190565b6020808252601c908201527f4d7573742062652074686520536574546f6b656e206d616e6167657200000000604082015260600190565b6020808252602d908201527f4d616e6167657220666565206d757374206265206c657373207468616e206d6160408201526c1e1a5b5d5b48185b1b1bddd959609a1b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526026908201527f4d6178206d616e6167657220666565206d757374206265206c657373207468616040820152656e203130302560d01b606082015260800190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715614d5657600080fd5b604052919050565b600067ffffffffffffffff821115614d74578081fd5b5060209081020190565b60005b83811015614d99578181015183820152602001614d81565b838111156126685750506000910152565b6001600160a01b038116811461179d57600080fdfea2646970667358221220f3a92032ffe683b93ca5ed77ac2fcf6bba051a83661fd30d30fbe69792ffc79d64736f6c634300060a0033", + "deployedBytecode": "0x6080604052600436106101445760003560e01c80637f977948116100b6578063b36f7e8c1161006f578063b36f7e8c1461038c578063d5f8394a146103ac578063df3fa714146103cc578063ee673ac4146103ec578063f529c18a146101fb578063f77c4791146104205761014b565b80637f977948146102d7578063847ef08d146102f757806391819fb31461030c5780639c5ad2831461032c5780639f6f6ba91461034c578063add7745a1461036c5761014b565b80632f879fa3116101085780632f879fa3146101fb57806330b305f91461021b5780633fc8cef31461023b5780634b79da0a1461025d57806364b2dc7a1461028a5780636ff7f6da146102b75761014b565b806302c619d01461015057806304f1b57114610165578063080b16f81461019b5780630e3af8ad146101bb578063281d0115146101db5761014b565b3661014b57005b600080fd5b61016361015e366004614024565b610435565b005b34801561017157600080fd5b50610185610180366004613ff9565b6105bd565b6040516101929190614338565b60405180910390f35b3480156101a757600080fd5b506101636101b6366004613e18565b6105f0565b3480156101c757600080fd5b506101636101d6366004613ff9565b610690565b3480156101e757600080fd5b506101636101f6366004613e18565b610723565b34801561020757600080fd5b50610185610216366004613e50565b610807565b34801561022757600080fd5b50610163610236366004613e90565b61081e565b34801561024757600080fd5b506102506108ac565b6040516101929190614163565b34801561026957600080fd5b5061027d610278366004613dfc565b6108d0565b604051610192919061421f565b34801561029657600080fd5b506102aa6102a5366004613e18565b610949565b604051610192919061426c565b3480156102c357600080fd5b506101856102d2366004613e50565b610969565b3480156102e357600080fd5b506101856102f2366004613e50565b610997565b34801561030357600080fd5b50610163610a39565b34801561031857600080fd5b50610163610327366004613e18565b610b57565b34801561033857600080fd5b506102aa610347366004613e50565b610cc9565b34801561035857600080fd5b50610163610367366004613e90565b610e81565b34801561037857600080fd5b506102aa610387366004613e50565b610f84565b34801561039857600080fd5b506101636103a7366004613eee565b61105e565b3480156103b857600080fd5b506101636103c7366004614099565b6113e3565b3480156103d857600080fd5b506101636103e7366004614065565b61164e565b3480156103f857600080fd5b5061040c610407366004613dfc565b611714565b604051610192989796959493929190614277565b34801561042c57600080fd5b50610250611769565b600260015414156104615760405162461bcd60e51b815260040161045890614cf2565b60405180910390fd5b60026001558261047081611778565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156104cb57600080fd5b505af11580156104df573d6000803e3d6000fd5b505050505061050f847f0000000000000000000000000000000000000000000000000000000000000000346117a0565b61053c847f000000000000000000000000000000000000000000000000000000000000000034338661180a565b610544613a70565b61056f857f00000000000000000000000000000000000000000000000000000000000000003461189a565b905061057c85858361198e565b61058685826119f1565b6105b2857f00000000000000000000000000000000000000000000000000000000000000008584611c95565b505060018055505050565b6001600160a01b0382166000908152600260208190526040822060050190839081106105e557fe5b015490505b92915050565b816105fa81611de2565b6001600160a01b0382166106205760405162461bcd60e51b8152600401610458906145d7565b6001600160a01b038381166000818152600260205260409081902060040180546001600160a01b0319169386169390931790925590517fff78699124ce6ab1e48255152542b253d1e5c0fc925308a48852e674777ace3590610683908590614163565b60405180910390a2505050565b8161069a81611de2565b6001600160a01b0383166000908152600260205260409020600901548211156106d55760405162461bcd60e51b8152600401610458906147d1565b6001600160a01b03831660008181526002602052604090819020600801849055517fd0db665d5987480b1c4e28f4484b1a9fabff141ffcb5a9ff9f384e4672155c0590610683908590614338565b8161072d81611de2565b6001600160a01b0380841660009081526003602090815260408083209386168352929052205460ff16156107735760405162461bcd60e51b8152600401610458906146ae565b6001600160a01b03838116600081815260026020908152604080832060039081018054600180820183559186528486200180546001600160a01b031916978a1697881790558585529083528184209584529490915290819020805460ff191690931790925590517f94257d51a6470b587cb1ae3068fee4bce93eff4d149a98bd05aee37ae491148790610683908590614163565b6000610814848484611e08565b90505b9392505050565b600260015414156108415760405162461bcd60e51b815260040161045890614cf2565b60026001558461085081611778565b61085b8686866117a0565b610868868686338661180a565b610870613a70565b61087b87878761189a565b905061088887858361198e565b610893878783611e28565b61089f87878584611c95565b5050600180555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03811660009081526002602090815260409182902060030180548351818402810184019094528084526060939283018282801561093d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161091f575b50505050509050919050565b600360209081526000928352604080842090915290825290205460ff1681565b600080610977858585611f13565b9050600061098b8683600160036001612083565b98975050505050505050565b6000806109aa8584600060026000612083565b925050506000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109e957600080fd5b505afa1580156109fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2191906140e2565b9050610a2f868684846120fa565b9695505050505050565b3360005b6001600160a01b038216600090815260026020526040902060030154811015610ac8576001600160a01b038216600090815260036020818152604080842060029092528320909101805491929184908110610a9457fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020805460ff19169055600101610a3d565b506001600160a01b0381166000908152600260208190526040822080546001600160a01b0319908116825560018201805482169055918101805490921690915590610b166003830182613abc565b6004820180546001600160a01b0319169055610b36600583016000613ada565b506000600782018190556008820181905560098201819055600a9091015550565b81610b6181611de2565b6001600160a01b0380841660009081526003602090815260408083209386168352929052205460ff16610ba65760405162461bcd60e51b81526004016104589061461a565b610c398260026000866001600160a01b03166001600160a01b03168152602001908152602001600020600301805480602002602001604051908101604052809291908181526020018280548015610c2657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c08575b50505050506122ac90919063ffffffff16565b6001600160a01b03841660009081526002602090815260409091208251610c6a936003909201929190910190613ae8565b506001600160a01b0380841660008181526003602090815260408083209487168352939052829020805460ff1916905590517f3c59157886f089a91f7813e86300f9f9b36289e41e7c09c70f9cc208b810cd9490610683908590614163565b600080846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d0557600080fd5b505afa158015610d19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3d91906140e2565b9050821580610d7257506001600160a01b0380861660009081526003602090815260408083209388168352929052205460ff16155b80610da757506001600160a01b0385166000908152600260205260409020600a0154610da4908463ffffffff6122f416565b81105b15610db6576000915050610817565b6000610dc3868686611f13565b90506000610dd78783600160036001612083565b925050506000610e61886001600160a01b03166366cb8d2f896040518263ffffffff1660e01b8152600401610e0c9190614163565b60206040518083038186803b158015610e2457600080fd5b505afa158015610e38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5c91906140e2565b612319565b905081610e74828663ffffffff61233f16565b1015945050505050610817565b60026001541415610ea45760405162461bcd60e51b815260040161045890614cf2565b600260015584610eb381611778565b610ebe8686866117a0565b610eca86853385612369565b610ed2613a70565b610edd8787876123e0565b9050610eea8785836124c3565b604051632770a7eb60e21b81526001600160a01b03881690639dc29fac90610f1890339089906004016141bb565b600060405180830381600087803b158015610f3257600080fd5b505af1158015610f46573d6000803e3d6000fd5b5050506060820151610f6d91506001600160a01b038916908890869063ffffffff61252616565b610f7887878361266e565b61089f878785846126bd565b600080846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc057600080fd5b505afa158015610fd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff891906140e2565b9050821580159061102e57506001600160a01b0380861660009081526003602090815260408083209388168352929052205460ff165b801561105557506001600160a01b0385166000908152600260205260409020600a01548110155b95945050505050565b813361106a82826127ab565b83611074816127d1565b6000846060015151116110995760405162461bcd60e51b8152600401610458906146e5565b6110a1612892565b8460c00151106110c35760405162461bcd60e51b815260040161045890614c77565b6110cb612892565b846101000151106110ee5760405162461bcd60e51b8152600401610458906148c7565b60c084015160a08501515111156111175760405162461bcd60e51b815260040161045890614a59565b60c084015160a08501516020015111156111435760405162461bcd60e51b81526004016104589061458f565b8361010001518460e00151111561116c5760405162461bcd60e51b815260040161045890614521565b60808401516001600160a01b03166111965760405162461bcd60e51b815260040161045890614aa0565b6000846101200151116111bb5760405162461bcd60e51b81526004016104589061445f565b60005b8460600151518110156112a3576001600160a01b038616600090815260036020526040812060608701518051919291849081106111f757fe5b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff161561123b5760405162461bcd60e51b815260040161045890614963565b6001600160a01b03861660009081526003602052604081206060870151805160019391908590811061126957fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff19169115159190911790556001016111be565b506001600160a01b03808616600090815260026020818152604092839020885181549086166001600160a01b0319918216178255828a015160018301805491881691831691909117905593890151928101805493909516929093169190911790925560608601518051879361131f926003850192910190613ae8565b5060808201516004820180546001600160a01b0319166001600160a01b0390921691909117905560a082015161135b9060058301906002613b49565b5060c0820151816007015560e08201518160080155610100820151816009015561012082015181600a0155905050846001600160a01b0316630ffe0f1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113c457600080fd5b505af11580156113d8573d6000803e3d6000fd5b505050505050505050565b600260015414156114065760405162461bcd60e51b815260040161045890614cf2565b60026001558361141581611778565b611440857f0000000000000000000000000000000000000000000000000000000000000000866117a0565b61144c85853385612369565b611454613a70565b61147f867f0000000000000000000000000000000000000000000000000000000000000000876123e0565b905061148c8685836124c3565b604051632770a7eb60e21b81526001600160a01b03871690639dc29fac906114ba90339089906004016141bb565b600060405180830381600087803b1580156114d457600080fd5b505af11580156114e8573d6000803e3d6000fd5b505050606082015161152f91506001600160a01b038816907f000000000000000000000000000000000000000000000000000000000000000090309063ffffffff61252616565b6060810151604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691632e1a7d4d9161157f9190600401614338565b600060405180830381600087803b15801561159957600080fd5b505af11580156115ad573d6000803e3d6000fd5b5050505060608101516040516001600160a01b038516916108fc811502916000818181858888f193505050501580156115ea573d6000803e3d6000fd5b50611616867f00000000000000000000000000000000000000000000000000000000000000008361266e565b611642867f000000000000000000000000000000000000000000000000000000000000000085846126bd565b50506001805550505050565b8261165881611de2565b6001600160a01b0384166000908152600260205260409020600701548311156116935760405162461bcd60e51b815260040161045890614be0565b8260026000866001600160a01b03166001600160a01b0316815260200190815260200160002060050183600281106116c757fe5b01556040516001600160a01b038516907f4e913bee7cf10ece89b3c5593df3898d1a324864d38052df88792a7d87a17488906117069086908690614d29565b60405180910390a250505050565b600260208190526000918252604090912080546001820154928201546004830154600784015460088501546009860154600a909601546001600160a01b03958616978616969486169590931693919290919088565b6000546001600160a01b031681565b6117818161289f565b61179d5760405162461bcd60e51b815260040161045890614417565b50565b600081116117c05760405162461bcd60e51b8152600401610458906143e9565b6001600160a01b0380841660009081526003602090815260408083209386168352929052205460ff166118055760405162461bcd60e51b81526004016104589061481a565b505050565b6001600160a01b0380861660009081526002602052604090205416801561189257604051633ed0b9fb60e21b81526001600160a01b0382169063fb42e7ec9061185f90899089908990899089906004016142db565b600060405180830381600087803b15801561187957600080fd5b505af115801561188d573d6000803e3d6000fd5b505050505b505050505050565b6118a2613a70565b6118aa613a70565b846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156118e357600080fd5b505afa1580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b91906140e2565b60a082015282815261193285846000600281612083565b606084018190526040840191909152602083019190915260a082015161195c9187918791906120fa565b608082015261196b85826129a3565b60e083015260c0820152611980858583612a7b565b610100820152949350505050565b6001600160a01b0383166000908152600260205260409020600a015460a082015110156119cd5760405162461bcd60e51b81526004016104589061472a565b81816080015110156118055760405162461bcd60e51b8152600401610458906144a9565b606081015160405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91611a429186916004016141bb565b602060405180830381600087803b158015611a5c57600080fd5b505af1158015611a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a949190613d50565b50602081015115611bc9577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6000809054906101000a90046001600160a01b03166001600160a01b031663469048406040518163ffffffff1660e01b815260040160206040518083038186803b158015611b1b57600080fd5b505afa158015611b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b539190613c98565b83602001516040518363ffffffff1660e01b8152600401611b759291906141bb565b602060405180830381600087803b158015611b8f57600080fd5b505af1158015611ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc79190613d50565b505b604081015115611c91576001600160a01b038281166000908152600260205260409081902060049081015484830151925163a9059cbb60e01b81527f000000000000000000000000000000000000000000000000000000000000000085169463a9059cbb94611c3f9493909116929091016141bb565b602060405180830381600087803b158015611c5957600080fd5b505af1158015611c6d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118059190613d50565b5050565b60e081015160405163c2de0e9d60e01b81526001600160a01b0386169163c2de0e9d91611cc59190600401614338565b600060405180830381600087803b158015611cdf57600080fd5b505af1158015611cf3573d6000803e3d6000fd5b505050610100820151611d1991506001600160a01b03861690859063ffffffff612ae916565b60808101516040516340c10f1960e01b81526001600160a01b038616916340c10f1991611d4a9186916004016141bb565b600060405180830381600087803b158015611d6457600080fd5b505af1158015611d78573d6000803e3d6000fd5b5050506001600160a01b03808616600081815260026020908152604091829020546080870151878401519288015193519496507fab151ef72553d84db96b5656139e68d5e348f8273d15b1724db8f3c09832d80e956117069533958b958d95909316939291614177565b611dec8133612c67565b6117785760405162461bcd60e51b815260040161045890614ba9565b50506001600160a01b031660009081526002602052604090206008015490565b611e388233858460600151612cf5565b602081015115611ed657611ed682336000809054906101000a90046001600160a01b03166001600160a01b031663469048406040518163ffffffff1660e01b815260040160206040518083038186803b158015611e9457600080fd5b505afa158015611ea8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ecc9190613c98565b8460200151612cf5565b604081015115611805576001600160a01b038084166000908152600260205260409081902060040154908301516118059285923392911690612cf5565b600080611f1f85612d01565b6001600160a01b0316636101c54086866040518363ffffffff1660e01b8152600401611f4c9291906142c1565b60206040518083038186803b158015611f6457600080fd5b505afa158015611f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9c91906140e2565b90506000611fb0848363ffffffff61233f16565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611fed57600080fd5b505afa158015612001573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202591906140fa565b60ff169050600061204083600a84900a63ffffffff61233f16565b9050600061204f898989611e08565b90506000612063838363ffffffff612d4216565b9050612075838263ffffffff612d8116565b9a9950505050505050505050565b60008060008060006120978a898989612dc3565b909250905060006120ae838b63ffffffff61233f16565b905060006120c2838c63ffffffff61233f16565b905060006120e6826120da8e8663ffffffff612d8116565b9063ffffffff612d8116565b929d919c50919a5098505050505050505050565b600080612108868686611e08565b9050600061211c858363ffffffff61233f16565b9050600061212988612d01565b6001600160a01b0316636101c54089896040518363ffffffff1660e01b81526004016121569291906142c1565b60206040518083038186803b15801561216e57600080fd5b505afa158015612182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a691906140e2565b90506000876001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156121e357600080fd5b505afa1580156121f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221b91906140fa565b60ff169050600061223688600a84900a63ffffffff612f5916565b9050600061225e600a84900a6122528b8863ffffffff612d8116565b9063ffffffff612f5916565b90506000612286826120da8561227a8d8a63ffffffff61233f16565b9063ffffffff6122f416565b905061229c81612252848c63ffffffff61233f16565b9c9b505050505050505050505050565b60606000806122bb8585612f77565b91509150806122dc5760405162461bcd60e51b815260040161045890614354565b60606122e88684612fda565b5093506105ea92505050565b6000828201838110156108175760405162461bcd60e51b8152600401610458906144ea565b60008082121561233b5760405162461bcd60e51b815260040161045890614851565b5090565b6000610817670de0b6b3a764000061235d858563ffffffff61310916565b9063ffffffff61314316565b6001600160a01b038085166000908152600260205260409020600101541680156123d957604051639b19c2bf60e01b81526001600160a01b03821690639b19c2bf906123bf90889088908890889060040161430d565b600060405180830381600087803b1580156113c457600080fd5b5050505050565b6123e8613a70565b6123f0613a70565b60808101839052612402858585611f13565b8082526124159086906001600381612083565b606084015260408084019190915260208084019290925280516318160ddd60e01b815290516001600160a01b038816926318160ddd9260048082019391829003018186803b15801561246657600080fd5b505afa15801561247a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249e91906140e2565b60a08201526124ae858483613185565b60e083015260c0820152611980858583613208565b6001600160a01b0383166000908152600260205260409020600a015460c082015110156125025760405162461bcd60e51b815260040161045890614651565b81816060015110156118055760405162461bcd60e51b815260040161045890614780565b8015612668576040516370a0823160e01b81526000906001600160a01b038516906370a082319061255b908890600401614163565b60206040518083038186803b15801561257357600080fd5b505afa158015612587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ab91906140e2565b90506125b9858585856132c2565b6040516370a0823160e01b81526000906001600160a01b038616906370a08231906125e8908990600401614163565b60206040518083038186803b15801561260057600080fd5b505afa158015612614573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263891906140e2565b905061264a828463ffffffff612d8116565b81146118925760405162461bcd60e51b815260040161045890614a22565b50505050565b61267d838383602001516133cc565b604081015115611805576001600160a01b03808416600081815260026020526040908190206004015490840151611805938692169063ffffffff61252616565b60e081015160405163c2de0e9d60e01b81526001600160a01b0386169163c2de0e9d916126ed9190600401614338565b600060405180830381600087803b15801561270757600080fd5b505af115801561271b573d6000803e3d6000fd5b50505061010082015161274191506001600160a01b03861690859063ffffffff612ae916565b6001600160a01b038085166000818152600260209081526040918290206001015460808601518684015192870151935194957f76608da3459f30443b27df4954c2ee5953695a78cf2327545bc5992eca749f4f956117069533958b958d9594169392909190614177565b6127b58282612c67565b611c915760405162461bcd60e51b815260040161045890614ba9565b600054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec90612801908490600401614163565b60206040518083038186803b15801561281957600080fd5b505afa15801561282d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128519190613d50565b61286d5760405162461bcd60e51b815260040161045890614b66565b61287681613473565b61179d5760405162461bcd60e51b815260040161045890614558565b670de0b6b3a76400005b90565b60008054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec906128d0908590600401614163565b60206040518083038186803b1580156128e857600080fd5b505afa1580156128fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129209190613d50565b80156105ea57506040516335fc6c9f60e21b81526001600160a01b0383169063d7f1b27c90612953903090600401614163565b60206040518083038186803b15801561296b57600080fd5b505afa15801561297f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea9190613d50565b60008060006129c38460a0015185608001516122f490919063ffffffff16565b90506000612a6c6129d3836134a2565b612a606129e38860a001516134a2565b896001600160a01b0316635230c3966040518163ffffffff1660e01b815260040160206040518083038186803b158015612a1c57600080fd5b505afa158015612a30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5491906140e2565b9063ffffffff6134c716565b9063ffffffff61353216565b919350909150505b9250929050565b600080612aad856001600160a01b03166366cb8d2f866040518263ffffffff1660e01b8152600401610e0c9190614163565b90506000612ad0846060015161227a8660a001518561233f90919063ffffffff16565b9050610a2f8460c0015182612f5990919063ffffffff16565b6000612af58484613596565b905080158015612b055750600082115b15612b7c57612b14848461361d565b612b77576040516304e3532760e41b81526001600160a01b03851690634e35327090612b44908690600401614163565b600060405180830381600087803b158015612b5e57600080fd5b505af1158015612b72573d6000803e3d6000fd5b505050505b612bf9565b808015612b87575081155b15612bf957612b96848461361d565b612bf957604051636f86c89760e01b81526001600160a01b03851690636f86c89790612bc6908690600401614163565b600060405180830381600087803b158015612be057600080fd5b505af1158015612bf4573d6000803e3d6000fd5b505050505b836001600160a01b0316632ba57d1784612c12856134a2565b6040518363ffffffff1660e01b8152600401612c2f9291906141bb565b600060405180830381600087803b158015612c4957600080fd5b505af1158015612c5d573d6000803e3d6000fd5b5050505050505050565b6000816001600160a01b0316836001600160a01b031663481c6a756040518163ffffffff1660e01b815260040160206040518083038186803b158015612cac57600080fd5b505afa158015612cc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce49190613c98565b6001600160a01b0316149392505050565b612668848484846136a9565b6001600160a01b038082166000908152600260208190526040822001549091168015612d2d5780610817565b600054610817906001600160a01b03166137cd565b6000821580612d4f575081155b15612d5c575060006105ea565b610817600161227a670de0b6b3a764000061235d836120da898963ffffffff61310916565b600061081783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061384d565b6000805460405163792aa04f60e01b8152829182916001600160a01b039091169063792aa04f90612dfa90309089906004016141bb565b60206040518083038186803b158015612e1257600080fd5b505afa158015612e26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e4a91906140e2565b6000805460405163792aa04f60e01b815292935090916001600160a01b039091169063792aa04f90612e829030908b906004016141bb565b60206040518083038186803b158015612e9a57600080fd5b505afa158015612eae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed291906140e2565b90506000600260008a6001600160a01b03166001600160a01b031681526020019081526020016000206005018660028110612f0957fe5b015490506000612f1f838363ffffffff61233f16565b90506000612f33838363ffffffff612d8116565b90506000612f47838763ffffffff6122f416565b9c919b50909950505050505050505050565b60006108178261235d85670de0b6b3a764000063ffffffff61310916565b81516000908190815b81811015612fca57846001600160a01b0316868281518110612f9e57fe5b60200260200101516001600160a01b03161415612fc257925060019150612a749050565b600101612f80565b5060001995600095509350505050565b81516060906000908084106130015760405162461bcd60e51b815260040161045890614383565b60606001820367ffffffffffffffff8111801561301d57600080fd5b50604051908082528060200260200182016040528015613047578160200160208202803683370190505b50905060005b858110156130955786818151811061306157fe5b602002602001015182828151811061307557fe5b6001600160a01b039092166020928302919091019091015260010161304d565b50600185015b828110156130e6578681815181106130af57fe5b60200260200101518260018303815181106130c657fe5b6001600160a01b039092166020928302919091019091015260010161309b565b50808686815181106130f457fe5b60200260200101519350935050509250929050565b600082613118575060006105ea565b8282028284828161312557fe5b04146108175760405162461bcd60e51b81526004016104589061499a565b600061081783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613879565b60008060006131a1858560a00151612d8190919063ffffffff16565b905060006131fa6131b1836134a2565b612a606131c18860a001516134a2565b8a6001600160a01b0316635230c3966040518163ffffffff1660e01b815260040160206040518083038186803b158015612a1c57600080fd5b919791965090945050505050565b60008061323a856001600160a01b03166366cb8d2f866040518263ffffffff1660e01b8152600401610e0c9190614163565b905060006132558460a001518361233f90919063ffffffff16565b9050600061327c856040015161227a876020015188606001516122f490919063ffffffff16565b90508082101561329e5760405162461bcd60e51b815260040161045890614914565b60c08501516132b790612252848463ffffffff612d8116565b979650505050505050565b801561266857606082826040516024016132dd9291906141bb565b60408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b179052516347b7819960e11b81529091506060906001600160a01b03871690638f6f03329061333c90889060009087906004016141f8565b600060405180830381600087803b15801561335657600080fd5b505af115801561336a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526133929190810190613d70565b80519091501561189257808060200190518101906133b09190613d50565b6118925760405162461bcd60e51b8152600401610458906143ba565b801561180557611805826000809054906101000a90046001600160a01b03166001600160a01b031663469048406040518163ffffffff1660e01b815260040160206040518083038186803b15801561342357600080fd5b505afa158015613437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061345b9190613c98565b6001600160a01b03861691908463ffffffff61252616565b6040516353bae5f760e01b81526000906001600160a01b038316906353bae5f790612953903090600401614163565b6000600160ff1b821061233b5760405162461bcd60e51b815260040161045890614b1e565b6000826134d6575060006105ea565b826000191480156134ea5750600160ff1b82145b156135075760405162461bcd60e51b8152600401610458906149db565b8282028284828161351457fe5b05146108175760405162461bcd60e51b8152600401610458906149db565b6000816135515760405162461bcd60e51b815260040161045890614cbd565b816000191480156135655750600160ff1b83145b156135825760405162461bcd60e51b815260040161045890614886565b600082848161358d57fe5b05949350505050565b600080836001600160a01b03166366cb8d2f846040518263ffffffff1660e01b81526004016135c59190614163565b60206040518083038186803b1580156135dd57600080fd5b505afa1580156135f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061361591906140e2565b139392505050565b600080836001600160a01b031663a7bdad03846040518263ffffffff1660e01b815260040161364c9190614163565b60006040518083038186803b15801561366457600080fd5b505afa158015613678573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526136a09190810190613cb4565b51119392505050565b8015612668576040516370a0823160e01b81526000906001600160a01b038616906370a08231906136de908690600401614163565b60206040518083038186803b1580156136f657600080fd5b505afa15801561370a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061372e91906140e2565b905061373c858585856138b0565b6040516370a0823160e01b81526000906001600160a01b038716906370a082319061376b908790600401614163565b60206040518083038186803b15801561378357600080fd5b505afa158015613797573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bb91906140e2565b905061264a828463ffffffff6122f416565b6040516373b2e76b60e11b81526000906001600160a01b0383169063e765ced6906137fd90600290600401614338565b60206040518083038186803b15801561381557600080fd5b505afa158015613829573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ea9190613c98565b600081848411156138715760405162461bcd60e51b81526004016104589190614341565b505050900390565b6000818361389a5760405162461bcd60e51b81526004016104589190614341565b5060008385816138a657fe5b0495945050505050565b612668846323b872dd60e01b8585856040516024016138d1939291906141d4565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060613958826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139929092919063ffffffff16565b80519091501561180557808060200190518101906139769190613d50565b6118055760405162461bcd60e51b815260040161045890614c2d565b60606108148484600085856139a685613a31565b6139c25760405162461bcd60e51b815260040161045890614ae7565b60006060866001600160a01b031685876040516139df9190614147565b60006040518083038185875af1925050503d8060008114613a1c576040519150601f19603f3d011682016040523d82523d6000602084013e613a21565b606091505b50915091506132b7828286613a37565b3b151590565b60608315613a46575081610817565b825115613a565782518084602001fd5b8160405162461bcd60e51b81526004016104589190614341565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b508054600082559060005260206000209081019061179d9190613b7f565b506000815560010160009055565b828054828255906000526020600020908101928215613b3d579160200282015b82811115613b3d57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613b08565b5061233b929150613b99565b8260028101928215613b77579160200282015b82811115613b77578251825591602001919060010190613b5c565b5061233b9291505b61289c91905b8082111561233b5760008155600101613b85565b61289c91905b8082111561233b5780546001600160a01b0319168155600101613b9f565b80356105ea81614daa565b600082601f830112613bd8578081fd5b8135613beb613be682614d5e565b614d37565b818152915060208083019084810181840286018201871015613c0c57600080fd5b60005b84811015613c34578135613c2281614daa565b84529282019290820190600101613c0f565b505050505092915050565b600082601f830112613c4f578081fd5b613c596040614d37565b9050808284604085011115613c6d57600080fd5b60005b6002811015613c8f578135835260209283019290910190600101613c70565b50505092915050565b600060208284031215613ca9578081fd5b815161081781614daa565b60006020808385031215613cc6578182fd5b825167ffffffffffffffff811115613cdc578283fd5b80840185601f820112613ced578384fd5b80519150613cfd613be683614d5e565b8281528381019082850185850284018601891015613d19578687fd5b8693505b84841015613d44578051613d3081614daa565b835260019390930192918501918501613d1d565b50979650505050505050565b600060208284031215613d61578081fd5b81518015158114610817578182fd5b600060208284031215613d81578081fd5b815167ffffffffffffffff80821115613d98578283fd5b81840185601f820112613da9578384fd5b8051925081831115613db9578384fd5b613dcc601f8401601f1916602001614d37565b9150828252856020848301011115613de2578384fd5b613df3836020840160208401614d7e565b50949350505050565b600060208284031215613e0d578081fd5b813561081781614daa565b60008060408385031215613e2a578081fd5b8235613e3581614daa565b91506020830135613e4581614daa565b809150509250929050565b600080600060608486031215613e64578081fd5b8335613e6f81614daa565b92506020840135613e7f81614daa565b929592945050506040919091013590565b600080600080600060a08688031215613ea7578283fd5b8535613eb281614daa565b94506020860135613ec281614daa565b935060408601359250606086013591506080860135613ee081614daa565b809150509295509295909350565b60008060408385031215613f00578182fd5b8235613f0b81614daa565b9150602083013567ffffffffffffffff80821115613f27578283fd5b8185016101608188031215613f3a578384fd5b6101409250613f4883614d37565b613f528883613bbd565b8152613f618860208401613bbd565b6020820152613f738860408401613bbd565b6040820152606082013583811115613f89578586fd5b613f9589828501613bc8565b606083015250613fa88860808401613bbd565b6080820152613fba8860a08401613c3f565b60a082015260e082013560c082015261010092508282013560e08201526101208083013584830152848301358183015250809450505050509250929050565b6000806040838503121561400b578182fd5b823561401681614daa565b946020939093013593505050565b600080600060608486031215614038578081fd5b833561404381614daa565b925060208401359150604084013561405a81614daa565b809150509250925092565b600080600060608486031215614079578081fd5b833561408481614daa565b95602085013595506040909401359392505050565b600080600080608085870312156140ae578182fd5b84356140b981614daa565b9350602085013592506040850135915060608501356140d781614daa565b939692955090935050565b6000602082840312156140f3578081fd5b5051919050565b60006020828403121561410b578081fd5b815160ff81168114610817578182fd5b60008151808452614133816020860160208601614d7e565b601f01601f19169290920160200192915050565b60008251614159818460208701614d7e565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03978816815295871660208701529386166040860152919094166060840152608083019390935260a082019290925260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060018060a01b038516825283602083015260606040830152611055606083018461411b565b6020808252825182820181905260009190848201906040850190845b818110156142605783516001600160a01b03168352928401929184019160010161423b565b50909695505050505050565b901515815260200190565b6001600160a01b03988916815296881660208801529487166040870152929095166060850152608084015260a083019390935260c082019290925260e08101919091526101000190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0395861681529385166020850152604084019290925283166060830152909116608082015260a00190565b6001600160a01b03948516815260208101939093529083166040830152909116606082015260800190565b90815260200190565b600060208252610817602083018461411b565b60208082526015908201527420b2323932b9b9903737ba1034b71030b93930bc9760591b604082015260600190565b60208082526018908201527f496e646578206d757374206265203c2041206c656e6774680000000000000000604082015260600190565b602080825260159082015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b60208082526014908201527305175616e74697479206d757374206265203e20360641b604082015260600190565b60208082526028908201527f4d75737420626520612076616c696420616e6420696e697469616c697a65642060408201526729b2ba2a37b5b2b760c11b606082015260800190565b6020808252602a908201527f4d696e20536574546f6b656e20737570706c79206d75737420626520677265616040820152690746572207468616e20360b41b606082015260800190565b60208082526021908201527f4d7573742062652067726561746572207468616e206d696e20536574546f6b656040820152603760f91b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601d908201527f5072656d69756d206d757374206265206c657373207468616e206d6178000000604082015260600190565b6020808252601e908201527f4d7573742062652070656e64696e6720696e697469616c697a6174696f6e0000604082015260600190565b60208082526028908201527f4d616e616765722072656465656d20666565206d757374206265206c657373206040820152670e8d0c2dc40dac2f60c31b606082015260800190565b60208082526023908201527f46656520726563697069656e74206d757374206e6f742062652030206164647260408201526265737360e81b606082015260800190565b6020808252601c908201527f5265736572766520617373657420646f6573206e6f7420657869737400000000604082015260600190565b60208082526038908201527f537570706c79206d7573742062652067726561746572207468616e206d696e6960408201527f6d756d20746f20656e61626c6520726564656d7074696f6e0000000000000000606082015260800190565b6020808252601c908201527f5265736572766520617373657420616c72656164792065786973747300000000604082015260600190565b60208082526025908201527f5265736572766520617373657473206d75737420626520677265617465722074604082015264068616e20360dc1b606082015260800190565b60208082526036908201527f537570706c79206d7573742062652067726561746572207468616e206d696e696040820152756d756d20746f20656e61626c652069737375616e636560501b606082015260800190565b60208082526031908201527f4d7573742062652067726561746572207468616e206d696e20726563656976656040820152702072657365727665207175616e7469747960781b606082015260800190565b60208082526029908201527f5072656d69756d206d757374206265206c657373207468616e206d6178696d756040820152681b48185b1b1bddd95960ba1b606082015260800190565b6020808252601b908201527f4d7573742062652076616c696420726573657276652061737365740000000000604082015260600190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602d908201527f4d6178207072656d69756d2070657263656e74616765206d757374206265206c60408201526c657373207468616e203130302560981b606082015260800190565b6020808252602f908201527f4d7573742062652067726561746572207468616e20746f74616c20617661696c60408201526e18589b194818dbdb1b185d195c985b608a1b606082015260800190565b6020808252601d908201527f5265736572766520617373657473206d75737420626520756e69717565000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b6020808252601d908201527f496e76616c696420706f7374207472616e736665722062616c616e6365000000604082015260600190565b60208082526027908201527f4d616e6167657220697373756520666565206d757374206265206c65737320746040820152660d0c2dc40dac2f60cb1b606082015260800190565b60208082526027908201527f46656520526563697069656e74206d757374206265206e6f6e2d7a65726f206160408201526632323932b9b99760c91b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b60208082526023908201527f4d75737420626520636f6e74726f6c6c65722d656e61626c656420536574546f60408201526235b2b760e91b606082015260800190565b6020808252601c908201527f4d7573742062652074686520536574546f6b656e206d616e6167657200000000604082015260600190565b6020808252602d908201527f4d616e6167657220666565206d757374206265206c657373207468616e206d6160408201526c1e1a5b5d5b48185b1b1bddd959609a1b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526026908201527f4d6178206d616e6167657220666565206d757374206265206c657373207468616040820152656e203130302560d01b606082015260800190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715614d5657600080fd5b604052919050565b600067ffffffffffffffff821115614d74578081fd5b5060209081020190565b60005b83811015614d99578181015183820152602001614d81565b838111156126685750506000910152565b6001600160a01b038116811461179d57600080fdfea2646970667358221220f3a92032ffe683b93ca5ed77ac2fcf6bba051a83661fd30d30fbe69792ffc79d64736f6c634300060a0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/set/DebtIssuanceModuleV3.json b/external/abi/set/DebtIssuanceModuleV3.json new file mode 100644 index 000000000..01e2ffb07 --- /dev/null +++ b/external/abi/set/DebtIssuanceModuleV3.json @@ -0,0 +1,579 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "DebtIssuanceModuleV3", + "sourceName": "contracts/protocol/modules/v1/DebtIssuanceModuleV3.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IController", + "name": "_controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenTransferBuffer", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_newFeeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newIssueFee", + "type": "uint256" + } + ], + "name": "IssueFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newRedeemFee", + "type": "uint256" + } + ], + "name": "RedeemFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_issuer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_hookContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_quantity", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_managerFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_protocolFee", + "type": "uint256" + } + ], + "name": "SetTokenIssued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_redeemer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_quantity", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_managerFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_protocolFee", + "type": "uint256" + } + ], + "name": "SetTokenRedeemed", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_quantity", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_isIssue", + "type": "bool" + } + ], + "name": "calculateTotalFees", + "outputs": [ + { + "internalType": "uint256", + "name": "totalQuantity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "managerFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolFee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + } + ], + "name": "getModuleIssuanceHooks", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_quantity", + "type": "uint256" + } + ], + "name": "getRequiredComponentIssuanceUnits", + "outputs": [ + { + "internalType": "address[]", + "name": "components", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "equityUnits", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "debtUnits", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_quantity", + "type": "uint256" + } + ], + "name": "getRequiredComponentRedemptionUnits", + "outputs": [ + { + "internalType": "address[]", + "name": "components", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "equityUnits", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "debtUnits", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxManagerFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_managerIssueFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_managerRedeemFee", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + }, + { + "internalType": "contract IManagerIssuanceHook", + "name": "_managerIssuanceHook", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_hook", + "type": "address" + } + ], + "name": "isModuleIssuanceHook", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "", + "type": "address" + } + ], + "name": "issuanceSettings", + "outputs": [ + { + "internalType": "uint256", + "name": "maxManagerFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "managerIssueFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "managerRedeemFee", + "type": "uint256" + }, + { + "internalType": "address", + "name": "feeRecipient", + "type": "address" + }, + { + "internalType": "contract IManagerIssuanceHook", + "name": "managerIssuanceHook", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_quantity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "issue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_quantity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + } + ], + "name": "registerToIssuanceModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "removeModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "tokenTransferBuffer", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + } + ], + "name": "unregisterFromIssuanceModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_newFeeRecipient", + "type": "address" + } + ], + "name": "updateFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_newIssueFee", + "type": "uint256" + } + ], + "name": "updateIssueFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_newRedeemFee", + "type": "uint256" + } + ], + "name": "updateRedeemFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + } + ], + "bytecode": "0x60a06040523480156200001157600080fd5b506040516200411838038062004118833981016040819052620000349162000062565b600080546001600160a01b0319166001600160a01b039390931692909217909155600180556080526200009c565b6000806040838503121562000075578182fd5b82516001600160a01b03811681146200008c578283fd5b6020939093015192949293505050565b608051614048620000d06000398061035952806106d2528061072c528061076752806116ed528061175252506140486000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80636dd86aa9116100a2578063cb38b22311610071578063cb38b2231461022e578063cd3c753914610241578063d9b1b6e014610265578063e079962014610278578063f77c47911461028b5761010b565b80636dd86aa9146101de578063847ef08d146101f15780638dda4037146101f9578063bf9fe1381461021b5761010b565b806363082446116100de578063630824461461018357806363b7b8ae146101a35780636b8e53b6146101b85780636d78f47a146101cb5761010b565b806308bc0e1114610110578063131e26b9146101395780635c833bfd1461015b5780635d98c37314610170575b600080fd5b61012361011e3660046133e1565b6102a0565b60405161013091906136ef565b60405180910390f35b61014c610147366004613435565b610319565b60405161013093929190613702565b61016e610169366004613460565b6103a7565b005b61016e61017e3660046133fd565b6105bc565b6101966101913660046133fd565b61069c565b6040516101309190613739565b6101ab6106d0565b6040516101309190613f4e565b61014c6101c6366004613435565b6106f4565b61016e6101d9366004613460565b6107d5565b61016e6101ec366004613435565b6109f3565b61016e610abf565b61020c6102073660046134a1565b610b42565b60405161013093929190613f57565b61016e6102293660046134d7565b610d18565b61016e61023c366004613435565b610e9b565b61025461024f3660046133e1565b610f66565b604051610130959493929190613f6d565b61016e6102733660046133e1565b610fa2565b61016e6102863660046133e1565b61105a565b610293611110565b604051610130919061362e565b6001600160a01b03811660009081526002602090815260409182902060050180548351818402810184019094528084526060939283018282801561030d57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102ef575b50505050509050919050565b6060806060610328858561111f565b9194509250905060005b825181101561039f57600083828151811061034957fe5b60200260200101511115610397577f000000000000000000000000000000000000000000000000000000000000000083828151811061038457fe5b6020026020010181815101915081815250505b600101610332565b509250925092565b600260015414156103d35760405162461bcd60e51b81526004016103ca90613ed4565b60405180910390fd5b6002600155826103e281611310565b600083116104025760405162461bcd60e51b81526004016103ca906138e9565b61040c8484611338565b6000846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561044757600080fd5b505afa15801561045b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047f919061355c565b604051632770a7eb60e21b81529091506001600160a01b03861690639dc29fac906104b09033908890600401613642565b600060405180830381600087803b1580156104ca57600080fd5b505af11580156104de573d6000803e3d6000fd5b5050505060008060006104f388886000610b42565b925092509250606080606061050a8b87600061143f565b919450925090506000610523888863ffffffff61159216565b90506105358c88600087868d876115db565b6105468c888c600088888e8861169a565b6105518c878761179e565b50505050856001600160a01b0316336001600160a01b0316896001600160a01b03167f54f4ed50e49638053e1655b45ee7ece434edd150e6771ac0aaedb8355be13a338a86866040516105a693929190613f57565b60405180910390a4505060018055505050505050565b816105c68161190e565b6001600160a01b0382166105ec5760405162461bcd60e51b81526004016103ca90613c2f565b6001600160a01b038084166000908152600260205260409020600301548382169116141561062c5760405162461bcd60e51b81526004016103ca90613bf8565b6001600160a01b038381166000818152600260205260409081902060030180546001600160a01b0319169386169390931790925590517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d39061068f90859061362e565b60405180910390a2505050565b6001600160a01b038083166000908152600260209081526040808320938516835260069093019052205460ff165b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060806060600061070786866000610b42565b505090506107178682600061143f565b9195509350915060005b83518110156107cc577f000000000000000000000000000000000000000000000000000000000000000084828151811061075757fe5b602002602001015111156107a9577f000000000000000000000000000000000000000000000000000000000000000084828151811061079257fe5b6020026020010181815103915081815250506107c4565b60008482815181106107b757fe5b6020026020010181815250505b600101610721565b50509250925092565b600260015414156107f85760405162461bcd60e51b81526004016103ca90613ed4565b60026001558261080781611310565b600083116108275760405162461bcd60e51b81526004016103ca906139c5565b600061083585853386611934565b905061084185856119d5565b6000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561087c57600080fd5b505afa158015610890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b4919061355c565b905060008060006108c789896001610b42565b92509250925060608060606108de8c87600161143f565b9194509250905060006108f7888863ffffffff611ad616565b905061090a8d888d600188888e8861169a565b61091a8d88600187868d876115db565b6109258d878761179e565b50506040516340c10f1960e01b81526001600160a01b038c1692506340c10f199150610957908a908c90600401613642565b600060405180830381600087803b15801561097157600080fd5b505af1158015610985573d6000803e3d6000fd5b50505050866001600160a01b0316336001600160a01b03168a6001600160a01b03167f1abc43bc3dd8b6c8bb9bcf1a14a84f83981bf5335700ef07758efefcb03a8c75888c87876040516109dc94939291906136c9565b60405180910390a450506001805550505050505050565b816109fd8161190e565b6001600160a01b038316600090815260026020526040902054821115610a355760405162461bcd60e51b81526004016103ca906137db565b6001600160a01b03831660009081526002602081905260409091200154821415610a715760405162461bcd60e51b81526004016103ca90613841565b6001600160a01b03831660008181526002602081905260409182902001849055517f676eda176d6aa20e9aa09b9ee131487c90646cd2b951176f75bd6fccdc0261779061068f908590613f4e565b3360009081526002602052604090206005015415610aef5760405162461bcd60e51b81526004016103ca90613e91565b3360009081526002602081905260408220828155600181018390559081018290556003810180546001600160a01b0319908116909155600482018054909116905590610b3e600583018261315f565b5050565b6000806000610b4f61317d565b6001600160a01b03808816600090815260026020818152604092839020835160c0810185528154815260018201548184015292810154838501526003810154851660608401526004810154909416608083015260058401805484518184028101840190955280855292949360a08601939092830182828015610bfa57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610bdc575b5050509190925250506000805460405163792aa04f60e01b815293945090926001600160a01b03909116915063792aa04f90610c3c9030908590600401613642565b60206040518083038186803b158015610c5457600080fd5b505afa158015610c68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8c919061355c565b9050600086610c9f578260400151610ca5565b82602001515b90506000610cb9828a63ffffffff611afb16565b9050610ccb818463ffffffff611afb16565b9450610cdd818663ffffffff61159216565b955087610cf957610cf4898263ffffffff61159216565b610d09565b610d09898263ffffffff611ad616565b96505050505093509350939050565b8533610d248282611b25565b87610d2e81611b4b565b87871115610d4e5760405162461bcd60e51b81526004016103ca90613bb6565b87861115610d6e5760405162461bcd60e51b81526004016103ca90613f0b565b6040805160c08101825289815260208082018a90528183018990526001600160a01b0388811660608401528716608083015282516000808252918101909352909160a08301915090526001600160a01b03808b1660009081526002602081815260409283902085518155858201516001820155928501519183019190915560608401516003830180549185166001600160a01b031992831617905560808501516004840180549190951691161790925560a083015180519192610e39926005850192909101906131c5565b50905050886001600160a01b0316630ffe0f1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e7857600080fd5b505af1158015610e8c573d6000803e3d6000fd5b50505050505050505050505050565b81610ea58161190e565b6001600160a01b038316600090815260026020526040902054821115610edd5760405162461bcd60e51b81526004016103ca9061398e565b6001600160a01b038316600090815260026020526040902060010154821415610f185760405162461bcd60e51b81526004016103ca90613b40565b6001600160a01b03831660008181526002602052604090819020600101849055517fd1de57b1db6a29967f337d6f744b7811624dabf2be924c65708336a81678d0779061068f908590613f4e565b60026020819052600091825260409091208054600182015492820154600383015460049093015491939290916001600160a01b03918216911685565b80610fac81611c0c565b81610fb681611310565b6001600160a01b038316600090815260026020908152604080832033845260060190915290205460ff1615610ffd5760405162461bcd60e51b81526004016103ca90613cad565b50506001600160a01b03166000908152600260209081526040808320600581018054600181810183559186528486200180546001600160a01b0319163390811790915585526006909101909252909120805460ff19169091179055565b8061106481611c0c565b8161106e81611310565b6001600160a01b038316600090815260026020908152604080832033845260060190915290205460ff166110b45760405162461bcd60e51b81526004016103ca906138b9565b6001600160a01b03831660009081526002602052604090206110df906005013363ffffffff611d4e16565b50506001600160a01b031660009081526002602090815260408083203384526006019091529020805460ff19169055565b6000546001600160a01b031681565b6060806060600061113286866001610b42565b50509050856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561116f57600080fd5b505afa158015611183573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a7919061355c565b6111c3576111b78682600161143f565b93509350935050611309565b60608060606111d189611e7a565b8251929550909350915060608167ffffffffffffffff811180156111f457600080fd5b5060405190808252806020026020018201604052801561121e578160200160208202803683370190505b50905060608267ffffffffffffffff8111801561123a57600080fd5b50604051908082528060200260200182016040528015611264578160200160208202803683370190505b50905060005b86518110156112f6576112998887838151811061128357fe5b602002602001015161229790919063ffffffff16565b8382815181106112a557fe5b6020026020010181815250506112d7888683815181106112c157fe5b6020026020010151611afb90919063ffffffff16565b8282815181106112e357fe5b602090810291909101015260010161126a565b5094985096509294506113099350505050565b9250925092565b611319816122ee565b6113355760405162461bcd60e51b81526004016103ca90613871565b50565b6001600160a01b0382166000908152600260209081526040918290206005018054835181840281018401909452808452606093928301828280156113a557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611387575b50939450600093505050505b8151811015611439578181815181106113c657fe5b60200260200101516001600160a01b0316633fe6106b85856040518363ffffffff1660e01b81526004016113fb929190613642565b600060405180830381600087803b15801561141557600080fd5b505af1158015611429573d6000803e3d6000fd5b5050600190920191506113b19050565b50505050565b606080606080606080611451896123f2565b8251929550909350915060608167ffffffffffffffff8111801561147457600080fd5b5060405190808252806020026020018201604052801561149e578160200160208202803683370190505b50905060608267ffffffffffffffff811180156114ba57600080fd5b506040519080825280602002602001820160405280156114e4578160200160208202803683370190505b50905060005b865181101561157e578a61150d576115088c8783815181106112c157fe5b61151d565b61151d8c87838151811061128357fe5b83828151811061152957fe5b6020026020010181815250508a61154f5761154a8c86838151811061128357fe5b61155f565b61155f8c8683815181106112c157fe5b82828151811061156b57fe5b60209081029190910101526001016114ea565b50949b909a50939850929650505050505050565b60006115d483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061277e565b9392505050565b60005b84518110156116905760008582815181106115f557fe5b60200260200101519050600085838151811061160d57fe5b602002602001015190506000811115611686578715611660576116358a8a84600160006127aa565b6116506001600160a01b038b1683338463ffffffff61295a16565b61165b8a8386612a6c565b611686565b61166c82338c84612ba6565b6116788a838784612bfe565b6116868a8a846000806127aa565b50506001016115de565b5050505050505050565b60005b84518110156117935760008582815181106116b457fe5b6020026020010151905060008583815181106116cc57fe5b6020026020010151905060008111156117895787156117325761171382338d7f00000000000000000000000000000000000000000000000000000000000000008501612ba6565b61171f8b838784612bfe565b61172d8b8b846001806127aa565b611789565b6117418b8b84600060016127aa565b61177e6001600160a01b038c16838b7f0000000000000000000000000000000000000000000000000000000000000000850363ffffffff61295a16565b6117898b8386612a6c565b505060010161169d565b505050505050505050565b8115611909576001600160a01b03808416600081815260026020526040908190206003015490516340c10f1960e01b815291926340c10f19926117e992909116908690600401613642565b600060405180830381600087803b15801561180357600080fd5b505af1158015611817573d6000803e3d6000fd5b50505050600081111561190957826001600160a01b03166340c10f196000809054906101000a90046001600160a01b03166001600160a01b031663469048406040518163ffffffff1660e01b815260040160206040518083038186803b15801561188057600080fd5b505afa158015611894573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b89190613272565b836040518363ffffffff1660e01b81526004016118d6929190613642565b600060405180830381600087803b1580156118f057600080fd5b505af1158015611904573d6000803e3d6000fd5b505050505b505050565b6119188133612ce5565b6113105760405162461bcd60e51b81526004016103ca90613db3565b6001600160a01b0380851660009081526002602052604081206004015490911680156119c75760405163a045808360e01b81526001600160a01b0382169063a04580839061198c908990899089908990600401613744565b600060405180830381600087803b1580156119a657600080fd5b505af11580156119ba573d6000803e3d6000fd5b50505050809150506119cd565b60009150505b949350505050565b6001600160a01b038216600090815260026020908152604091829020600501805483518184028101840190945280845260609392830182828015611a4257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611a24575b50939450600093505050505b815181101561143957818181518110611a6357fe5b60200260200101516001600160a01b031663c153dd0785856040518363ffffffff1660e01b8152600401611a98929190613642565b600060405180830381600087803b158015611ab257600080fd5b505af1158015611ac6573d6000803e3d6000fd5b505060019092019150611a4e9050565b6000828201838110156115d45760405162461bcd60e51b81526004016103ca90613920565b60006115d4670de0b6b3a7640000611b19858563ffffffff612d7316565b9063ffffffff612dad16565b611b2f8282612ce5565b610b3e5760405162461bcd60e51b81526004016103ca90613db3565b600054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec90611b7b90849060040161362e565b60206040518083038186803b158015611b9357600080fd5b505afa158015611ba7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcb9190613339565b611be75760405162461bcd60e51b81526004016103ca90613d70565b611bf081612def565b6113355760405162461bcd60e51b81526004016103ca90613957565b6002604051631ade272960e11b81526001600160a01b038316906335bc4e5290611c3a90339060040161362e565b60206040518083038186803b158015611c5257600080fd5b505afa158015611c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8a919061353d565b6002811115611c9557fe5b14611cb25760405162461bcd60e51b81526004016103ca90613ac8565b6000546040516342f6e38960e01b81526001600160a01b03909116906342f6e38990611ce290339060040161362e565b60206040518083038186803b158015611cfa57600080fd5b505afa158015611d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d329190613339565b6113355760405162461bcd60e51b81526004016103ca90613d2c565b600080611db484805480602002602001604051908101604052809291908181526020018280548015611da957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d8b575b505050505084612e1e565b9150915080611dd55760405162461bcd60e51b81526004016103ca906137ac565b835460001901828114611e4757848181548110611dee57fe5b9060005260206000200160009054906101000a90046001600160a01b0316858481548110611e1857fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b84805480611e5157fe5b600082815260209020810160001990810180546001600160a01b03191690550190555050505050565b606080606080846001600160a01b03166399d50d5d6040518163ffffffff1660e01b815260040160006040518083038186803b158015611eb957600080fd5b505afa158015611ecd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ef5919081019061328e565b805190915060608167ffffffffffffffff81118015611f1357600080fd5b50604051908082528060200260200182016040528015611f3d578160200160208202803683370190505b50905060608267ffffffffffffffff81118015611f5957600080fd5b50604051908082528060200260200182016040528015611f83578160200160208202803683370190505b5090506000886001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611fc157600080fd5b505afa158015611fd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ff9919061355c565b905060005b855181101561228857600086828151811061201557fe5b6020026020010151905060006120b56120b0836001600160a01b03166370a082318f6040518263ffffffff1660e01b8152600401612053919061362e565b60206040518083038186803b15801561206b57600080fd5b505afa15801561207f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a3919061355c565b869063ffffffff612e8416565b612e96565b60405163a7bdad0360e01b81529091506000906060906001600160a01b038f169063a7bdad03906120ea90879060040161362e565b60006040518083038186803b15801561210257600080fd5b505afa158015612116573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261213e919081019061328e565b8051909150156122275760005b81518110156122255760008f6001600160a01b03166322ebeba48785858151811061217257fe5b60200260200101516040518363ffffffff1660e01b815260040161219792919061365b565b60206040518083038186803b1580156121af57600080fd5b505afa1580156121c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e7919061355c565b9050600081131561220957612202858263ffffffff612ebf16565b945061221c565b612219848263ffffffff612ebf16565b93505b5060010161214b565b505b61223083612f05565b88868151811061223c57fe5b602090810291909101015261226161225c8360001963ffffffff612f2716565b612f05565b87868151811061226d57fe5b6020908102919091010152505060019092019150611ffe9050565b50939891975095509350505050565b60008215806122a4575081155b156122b1575060006106ca565b6115d460016122e2670de0b6b3a7640000611b19836122d6898963ffffffff612d7316565b9063ffffffff61159216565b9063ffffffff611ad616565b60008054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec9061231f90859060040161362e565b60206040518083038186803b15801561233757600080fd5b505afa15801561234b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236f9190613339565b80156106ca57506040516335fc6c9f60e21b81526001600160a01b0383169063d7f1b27c906123a290309060040161362e565b60206040518083038186803b1580156123ba57600080fd5b505afa1580156123ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ca9190613339565b606080606080846001600160a01b03166399d50d5d6040518163ffffffff1660e01b815260040160006040518083038186803b15801561243157600080fd5b505afa158015612445573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261246d919081019061328e565b805190915060608167ffffffffffffffff8111801561248b57600080fd5b506040519080825280602002602001820160405280156124b5578160200160208202803683370190505b50905060608267ffffffffffffffff811180156124d157600080fd5b506040519080825280602002602001820160405280156124fb578160200160208202803683370190505b50905060005b845181101561276e57600085828151811061251857fe5b6020026020010151905060008a6001600160a01b03166366cb8d2f836040518263ffffffff1660e01b8152600401612550919061362e565b60206040518083038186803b15801561256857600080fd5b505afa15801561257c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a0919061355c565b60405163a7bdad0360e01b81529091506000906060906001600160a01b038e169063a7bdad03906125d590879060040161362e565b60006040518083038186803b1580156125ed57600080fd5b505afa158015612601573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612629919081019061328e565b8051909150156127125760005b81518110156127105760008e6001600160a01b03166322ebeba48785858151811061265d57fe5b60200260200101516040518363ffffffff1660e01b815260040161268292919061365b565b60206040518083038186803b15801561269a57600080fd5b505afa1580156126ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d2919061355c565b905060008113156126f4576126ed858263ffffffff612ebf16565b9450612707565b612704848263ffffffff612ebf16565b93505b50600101612636565b505b61271b83612f05565b87868151811061272757fe5b602090810291909101015261274761225c8360001963ffffffff612f2716565b86868151811061275357fe5b60209081029190910101525050600190920191506125019050565b5092979096509194509092505050565b600081848411156127a25760405162461bcd60e51b81526004016103ca9190613799565b505050900390565b60405163a7bdad0360e01b81526060906001600160a01b0387169063a7bdad03906127d990879060040161362e565b60006040518083038186803b1580156127f157600080fd5b505afa158015612805573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261282d919081019061328e565b805190915083156128cc5760005b818110156128c65782818151811061284f57fe5b60200260200101516001600160a01b0316630fb96b21898989886040518563ffffffff1660e01b8152600401612888949392919061376f565b600060405180830381600087803b1580156128a257600080fd5b505af11580156128b6573d6000803e3d6000fd5b50506001909201915061283b9050565b50611904565b60005b81811015611690578281815181106128e357fe5b60200260200101516001600160a01b031663c137f4d7898989886040518563ffffffff1660e01b815260040161291c949392919061376f565b600060405180830381600087803b15801561293657600080fd5b505af115801561294a573d6000803e3d6000fd5b5050600190920191506128cf9050565b80156114395760608282604051602401612975929190613642565b60408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b179052516347b7819960e11b81529091506060906001600160a01b03871690638f6f0332906129d49088906000908790600401613699565b600060405180830381600087803b1580156129ee57600080fd5b505af1158015612a02573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612a2a9190810190613355565b805190915015612a645780806020019051810190612a489190613339565b612a645760405162461bcd60e51b81526004016103ca90613812565b505050505050565b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190612a9b90879060040161362e565b60206040518083038186803b158015612ab357600080fd5b505afa158015612ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aeb919061355c565b90506000612b6e856001600160a01b03166366cb8d2f866040518263ffffffff1660e01b8152600401612b1e919061362e565b60206040518083038186803b158015612b3657600080fd5b505afa158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225c919061355c565b9050612b80838263ffffffff61229716565b821015612b9f5760405162461bcd60e51b81526004016103ca90613e34565b5050505050565b611439846323b872dd60e01b858585604051602401612bc793929190613675565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612f92565b6040516370a0823160e01b81526000906001600160a01b038516906370a0823190612c2d90889060040161362e565b60206040518083038186803b158015612c4557600080fd5b505afa158015612c59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7d919061355c565b90506000612cb0866001600160a01b03166366cb8d2f876040518263ffffffff1660e01b8152600401612b1e919061362e565b9050612cc6836122e2868463ffffffff61229716565b821015612a645760405162461bcd60e51b81526004016103ca90613a3d565b6000816001600160a01b0316836001600160a01b031663481c6a756040518163ffffffff1660e01b815260040160206040518083038186803b158015612d2a57600080fd5b505afa158015612d3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d629190613272565b6001600160a01b0316149392505050565b600082612d82575060006106ca565b82820282848281612d8f57fe5b04146115d45760405162461bcd60e51b81526004016103ca90613aff565b60006115d483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613021565b6040516353bae5f760e01b81526000906001600160a01b038316906353bae5f7906123a290309060040161362e565b81516000908190815b81811015612e7157846001600160a01b0316868281518110612e4557fe5b60200260200101516001600160a01b03161415612e6957925060019150612e7d9050565b600101612e27565b50600019600092509250505b9250929050565b60006115d4828463ffffffff61305816565b6000600160ff1b8210612ebb5760405162461bcd60e51b81526004016103ca90613ce4565b5090565b6000828201818312801590612ed45750838112155b80612ee95750600083128015612ee957508381125b6115d45760405162461bcd60e51b81526004016103ca906139fc565b600080821215612ebb5760405162461bcd60e51b81526004016103ca90613a93565b600082612f36575060006106ca565b82600019148015612f4a5750600160ff1b82145b15612f675760405162461bcd60e51b81526004016103ca90613b6f565b82820282848281612f7457fe5b05146115d45760405162461bcd60e51b81526004016103ca90613b6f565b6060612fe7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130769092919063ffffffff16565b80519091501561190957808060200190518101906130059190613339565b6119095760405162461bcd60e51b81526004016103ca90613dea565b600081836130425760405162461bcd60e51b81526004016103ca9190613799565b50600083858161304e57fe5b0495945050505050565b60006115d482611b1985670de0b6b3a764000063ffffffff612d7316565b60606119cd84846000858561308a85613120565b6130a65760405162461bcd60e51b81526004016103ca90613c76565b60006060866001600160a01b031685876040516130c39190613612565b60006040518083038185875af1925050503d8060008114613100576040519150601f19603f3d011682016040523d82523d6000602084013e613105565b606091505b5091509150613115828286613126565b979650505050505050565b3b151590565b606083156131355750816115d4565b8251156131455782518084602001fd5b8160405162461bcd60e51b81526004016103ca9190613799565b50805460008255906000526020600020908101906113359190613226565b6040518060c0016040528060008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b03168152602001606081525090565b82805482825590600052602060002090810192821561321a579160200282015b8281111561321a57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906131e5565b50612ebb929150613243565b61324091905b80821115612ebb576000815560010161322c565b90565b61324091905b80821115612ebb5780546001600160a01b0319168155600101613249565b80516106ca81613fef565b600060208284031215613283578081fd5b81516115d481613fef565b600060208083850312156132a0578182fd5b825167ffffffffffffffff808211156132b7578384fd5b81850186601f8201126132c8578485fd5b80519250818311156132d8578485fd5b83830291506132e8848301613f9c565b8381528481019082860184840187018a1015613302578788fd5b8794505b8585101561332c576133188a82613267565b835260019490940193918601918601613306565b5098975050505050505050565b60006020828403121561334a578081fd5b81516115d481614004565b600060208284031215613366578081fd5b815167ffffffffffffffff8082111561337d578283fd5b81840185601f82011261338e578384fd5b805192508183111561339e578384fd5b6133b1601f8401601f1916602001613f9c565b91508282528560208483010111156133c7578384fd5b6133d8836020840160208401613fc3565b50949350505050565b6000602082840312156133f2578081fd5b81356115d481613fef565b6000806040838503121561340f578081fd5b823561341a81613fef565b9150602083013561342a81613fef565b809150509250929050565b60008060408385031215613447578182fd5b823561345281613fef565b946020939093013593505050565b600080600060608486031215613474578081fd5b833561347f81613fef565b925060208401359150604084013561349681613fef565b809150509250925092565b6000806000606084860312156134b5578283fd5b83356134c081613fef565b925060208401359150604084013561349681614004565b60008060008060008060c087890312156134ef578182fd5b86356134fa81613fef565b9550602087013594506040870135935060608701359250608087013561351f81613fef565b915060a087013561352f81613fef565b809150509295509295509295565b60006020828403121561354e578081fd5b8151600381106115d4578182fd5b60006020828403121561356d578081fd5b5051919050565b6000815180845260208085019450808401835b838110156135ac5781516001600160a01b031687529582019590820190600101613587565b509495945050505050565b6000815180845260208085019450808401835b838110156135ac578151875295820195908201906001016135ca565b600081518084526135fe816020860160208601613fc3565b601f01601f19169290920160200192915050565b60008251613624818460208701613fc3565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060018060a01b0385168252836020830152606060408301526136c060608301846135e6565b95945050505050565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6000602082526115d46020830184613574565b6000606082526137156060830186613574565b828103602084015261372781866135b7565b838103604085015261311581866135b7565b901515815260200190565b6001600160a01b03948516815260208101939093529083166040830152909116606082015260800190565b6001600160a01b039485168152602081019390935292166040820152901515606082015260800190565b6000602082526115d460208301846135e6565b60208082526015908201527420b2323932b9b9903737ba1034b71030b93930bc9760591b604082015260600190565b6020808252601f908201527f52656465656d206665652063616e277420657863656564206d6178696d756d00604082015260600190565b602080825260159082015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b60208082526016908201527514d85b59481c995919595b48199959481c185cdcd95960521b604082015260600190565b60208082526028908201527f4d75737420626520612076616c696420616e6420696e697469616c697a65642060408201526729b2ba2a37b5b2b760c11b606082015260800190565b60208082526016908201527526b7b23ab632903737ba103932b3b4b9ba32b932b21760511b604082015260600190565b6020808252601b908201527f52656465656d207175616e74697479206d757374206265203e20300000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601e908201527f4d7573742062652070656e64696e6720696e697469616c697a6174696f6e0000604082015260600190565b6020808252601e908201527f4973737565206665652063616e277420657863656564206d6178696d756d0000604082015260600190565b6020808252601a908201527f4973737565207175616e74697479206d757374206265203e2030000000000000604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526036908201527f496e76616c6964207472616e7366657220696e2e20526573756c747320696e206040820152753ab73232b931b7b63630ba32b930b634bd30ba34b7b760511b606082015260800190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b60208082526018908201527f4f6e6c7920746865206d6f64756c652063616e2063616c6c0000000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526015908201527414d85b59481a5cdcdd5948199959481c185cdcd959605a1b604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b60208082526022908201527f4973737565206665652063616e277420657863656564206d6178696d756d2066604082015261656560f01b606082015260800190565b60208082526019908201527f53616d652066656520726563697069656e742070617373656400000000000000604082015260600190565b60208082526027908201527f46656520526563697069656e74206d757374206265206e6f6e2d7a65726f206160408201526632323932b9b99760c91b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252601a908201527f4d6f64756c6520616c726561647920726567697374657265642e000000000000604082015260600190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b60208082526024908201527f4d6f64756c65206d75737420626520656e61626c6564206f6e20636f6e74726f604082015263363632b960e11b606082015260800190565b60208082526023908201527f4d75737420626520636f6e74726f6c6c65722d656e61626c656420536574546f60408201526235b2b760e91b606082015260800190565b6020808252601c908201527f4d7573742062652074686520536574546f6b656e206d616e6167657200000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526037908201527f496e76616c6964207472616e73666572206f75742e20526573756c747320696e60408201527f20756e646572636f6c6c61746572616c697a6174696f6e000000000000000000606082015260800190565b60208082526023908201527f52656769737465726564206d6f64756c6573206d7573742062652072656d6f7660408201526232b21760e91b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526023908201527f52656465656d206665652063616e277420657863656564206d6178696d756d2060408201526266656560e81b606082015260800190565b90815260200190565b9283526020830191909152604082015260600190565b948552602085019390935260408401919091526001600160a01b03908116606084015216608082015260a00190565b60405181810167ffffffffffffffff81118282101715613fbb57600080fd5b604052919050565b60005b83811015613fde578181015183820152602001613fc6565b838111156114395750506000910152565b6001600160a01b038116811461133557600080fd5b801515811461133557600080fdfea26469706673582212204bb7104025feb18fd01374aa5ffdd724e8b387b6b706f18d39c7a0ee218bce7664736f6c634300060a0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80636dd86aa9116100a2578063cb38b22311610071578063cb38b2231461022e578063cd3c753914610241578063d9b1b6e014610265578063e079962014610278578063f77c47911461028b5761010b565b80636dd86aa9146101de578063847ef08d146101f15780638dda4037146101f9578063bf9fe1381461021b5761010b565b806363082446116100de578063630824461461018357806363b7b8ae146101a35780636b8e53b6146101b85780636d78f47a146101cb5761010b565b806308bc0e1114610110578063131e26b9146101395780635c833bfd1461015b5780635d98c37314610170575b600080fd5b61012361011e3660046133e1565b6102a0565b60405161013091906136ef565b60405180910390f35b61014c610147366004613435565b610319565b60405161013093929190613702565b61016e610169366004613460565b6103a7565b005b61016e61017e3660046133fd565b6105bc565b6101966101913660046133fd565b61069c565b6040516101309190613739565b6101ab6106d0565b6040516101309190613f4e565b61014c6101c6366004613435565b6106f4565b61016e6101d9366004613460565b6107d5565b61016e6101ec366004613435565b6109f3565b61016e610abf565b61020c6102073660046134a1565b610b42565b60405161013093929190613f57565b61016e6102293660046134d7565b610d18565b61016e61023c366004613435565b610e9b565b61025461024f3660046133e1565b610f66565b604051610130959493929190613f6d565b61016e6102733660046133e1565b610fa2565b61016e6102863660046133e1565b61105a565b610293611110565b604051610130919061362e565b6001600160a01b03811660009081526002602090815260409182902060050180548351818402810184019094528084526060939283018282801561030d57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102ef575b50505050509050919050565b6060806060610328858561111f565b9194509250905060005b825181101561039f57600083828151811061034957fe5b60200260200101511115610397577f000000000000000000000000000000000000000000000000000000000000000083828151811061038457fe5b6020026020010181815101915081815250505b600101610332565b509250925092565b600260015414156103d35760405162461bcd60e51b81526004016103ca90613ed4565b60405180910390fd5b6002600155826103e281611310565b600083116104025760405162461bcd60e51b81526004016103ca906138e9565b61040c8484611338565b6000846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561044757600080fd5b505afa15801561045b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047f919061355c565b604051632770a7eb60e21b81529091506001600160a01b03861690639dc29fac906104b09033908890600401613642565b600060405180830381600087803b1580156104ca57600080fd5b505af11580156104de573d6000803e3d6000fd5b5050505060008060006104f388886000610b42565b925092509250606080606061050a8b87600061143f565b919450925090506000610523888863ffffffff61159216565b90506105358c88600087868d876115db565b6105468c888c600088888e8861169a565b6105518c878761179e565b50505050856001600160a01b0316336001600160a01b0316896001600160a01b03167f54f4ed50e49638053e1655b45ee7ece434edd150e6771ac0aaedb8355be13a338a86866040516105a693929190613f57565b60405180910390a4505060018055505050505050565b816105c68161190e565b6001600160a01b0382166105ec5760405162461bcd60e51b81526004016103ca90613c2f565b6001600160a01b038084166000908152600260205260409020600301548382169116141561062c5760405162461bcd60e51b81526004016103ca90613bf8565b6001600160a01b038381166000818152600260205260409081902060030180546001600160a01b0319169386169390931790925590517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d39061068f90859061362e565b60405180910390a2505050565b6001600160a01b038083166000908152600260209081526040808320938516835260069093019052205460ff165b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060806060600061070786866000610b42565b505090506107178682600061143f565b9195509350915060005b83518110156107cc577f000000000000000000000000000000000000000000000000000000000000000084828151811061075757fe5b602002602001015111156107a9577f000000000000000000000000000000000000000000000000000000000000000084828151811061079257fe5b6020026020010181815103915081815250506107c4565b60008482815181106107b757fe5b6020026020010181815250505b600101610721565b50509250925092565b600260015414156107f85760405162461bcd60e51b81526004016103ca90613ed4565b60026001558261080781611310565b600083116108275760405162461bcd60e51b81526004016103ca906139c5565b600061083585853386611934565b905061084185856119d5565b6000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561087c57600080fd5b505afa158015610890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b4919061355c565b905060008060006108c789896001610b42565b92509250925060608060606108de8c87600161143f565b9194509250905060006108f7888863ffffffff611ad616565b905061090a8d888d600188888e8861169a565b61091a8d88600187868d876115db565b6109258d878761179e565b50506040516340c10f1960e01b81526001600160a01b038c1692506340c10f199150610957908a908c90600401613642565b600060405180830381600087803b15801561097157600080fd5b505af1158015610985573d6000803e3d6000fd5b50505050866001600160a01b0316336001600160a01b03168a6001600160a01b03167f1abc43bc3dd8b6c8bb9bcf1a14a84f83981bf5335700ef07758efefcb03a8c75888c87876040516109dc94939291906136c9565b60405180910390a450506001805550505050505050565b816109fd8161190e565b6001600160a01b038316600090815260026020526040902054821115610a355760405162461bcd60e51b81526004016103ca906137db565b6001600160a01b03831660009081526002602081905260409091200154821415610a715760405162461bcd60e51b81526004016103ca90613841565b6001600160a01b03831660008181526002602081905260409182902001849055517f676eda176d6aa20e9aa09b9ee131487c90646cd2b951176f75bd6fccdc0261779061068f908590613f4e565b3360009081526002602052604090206005015415610aef5760405162461bcd60e51b81526004016103ca90613e91565b3360009081526002602081905260408220828155600181018390559081018290556003810180546001600160a01b0319908116909155600482018054909116905590610b3e600583018261315f565b5050565b6000806000610b4f61317d565b6001600160a01b03808816600090815260026020818152604092839020835160c0810185528154815260018201548184015292810154838501526003810154851660608401526004810154909416608083015260058401805484518184028101840190955280855292949360a08601939092830182828015610bfa57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610bdc575b5050509190925250506000805460405163792aa04f60e01b815293945090926001600160a01b03909116915063792aa04f90610c3c9030908590600401613642565b60206040518083038186803b158015610c5457600080fd5b505afa158015610c68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8c919061355c565b9050600086610c9f578260400151610ca5565b82602001515b90506000610cb9828a63ffffffff611afb16565b9050610ccb818463ffffffff611afb16565b9450610cdd818663ffffffff61159216565b955087610cf957610cf4898263ffffffff61159216565b610d09565b610d09898263ffffffff611ad616565b96505050505093509350939050565b8533610d248282611b25565b87610d2e81611b4b565b87871115610d4e5760405162461bcd60e51b81526004016103ca90613bb6565b87861115610d6e5760405162461bcd60e51b81526004016103ca90613f0b565b6040805160c08101825289815260208082018a90528183018990526001600160a01b0388811660608401528716608083015282516000808252918101909352909160a08301915090526001600160a01b03808b1660009081526002602081815260409283902085518155858201516001820155928501519183019190915560608401516003830180549185166001600160a01b031992831617905560808501516004840180549190951691161790925560a083015180519192610e39926005850192909101906131c5565b50905050886001600160a01b0316630ffe0f1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e7857600080fd5b505af1158015610e8c573d6000803e3d6000fd5b50505050505050505050505050565b81610ea58161190e565b6001600160a01b038316600090815260026020526040902054821115610edd5760405162461bcd60e51b81526004016103ca9061398e565b6001600160a01b038316600090815260026020526040902060010154821415610f185760405162461bcd60e51b81526004016103ca90613b40565b6001600160a01b03831660008181526002602052604090819020600101849055517fd1de57b1db6a29967f337d6f744b7811624dabf2be924c65708336a81678d0779061068f908590613f4e565b60026020819052600091825260409091208054600182015492820154600383015460049093015491939290916001600160a01b03918216911685565b80610fac81611c0c565b81610fb681611310565b6001600160a01b038316600090815260026020908152604080832033845260060190915290205460ff1615610ffd5760405162461bcd60e51b81526004016103ca90613cad565b50506001600160a01b03166000908152600260209081526040808320600581018054600181810183559186528486200180546001600160a01b0319163390811790915585526006909101909252909120805460ff19169091179055565b8061106481611c0c565b8161106e81611310565b6001600160a01b038316600090815260026020908152604080832033845260060190915290205460ff166110b45760405162461bcd60e51b81526004016103ca906138b9565b6001600160a01b03831660009081526002602052604090206110df906005013363ffffffff611d4e16565b50506001600160a01b031660009081526002602090815260408083203384526006019091529020805460ff19169055565b6000546001600160a01b031681565b6060806060600061113286866001610b42565b50509050856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561116f57600080fd5b505afa158015611183573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a7919061355c565b6111c3576111b78682600161143f565b93509350935050611309565b60608060606111d189611e7a565b8251929550909350915060608167ffffffffffffffff811180156111f457600080fd5b5060405190808252806020026020018201604052801561121e578160200160208202803683370190505b50905060608267ffffffffffffffff8111801561123a57600080fd5b50604051908082528060200260200182016040528015611264578160200160208202803683370190505b50905060005b86518110156112f6576112998887838151811061128357fe5b602002602001015161229790919063ffffffff16565b8382815181106112a557fe5b6020026020010181815250506112d7888683815181106112c157fe5b6020026020010151611afb90919063ffffffff16565b8282815181106112e357fe5b602090810291909101015260010161126a565b5094985096509294506113099350505050565b9250925092565b611319816122ee565b6113355760405162461bcd60e51b81526004016103ca90613871565b50565b6001600160a01b0382166000908152600260209081526040918290206005018054835181840281018401909452808452606093928301828280156113a557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611387575b50939450600093505050505b8151811015611439578181815181106113c657fe5b60200260200101516001600160a01b0316633fe6106b85856040518363ffffffff1660e01b81526004016113fb929190613642565b600060405180830381600087803b15801561141557600080fd5b505af1158015611429573d6000803e3d6000fd5b5050600190920191506113b19050565b50505050565b606080606080606080611451896123f2565b8251929550909350915060608167ffffffffffffffff8111801561147457600080fd5b5060405190808252806020026020018201604052801561149e578160200160208202803683370190505b50905060608267ffffffffffffffff811180156114ba57600080fd5b506040519080825280602002602001820160405280156114e4578160200160208202803683370190505b50905060005b865181101561157e578a61150d576115088c8783815181106112c157fe5b61151d565b61151d8c87838151811061128357fe5b83828151811061152957fe5b6020026020010181815250508a61154f5761154a8c86838151811061128357fe5b61155f565b61155f8c8683815181106112c157fe5b82828151811061156b57fe5b60209081029190910101526001016114ea565b50949b909a50939850929650505050505050565b60006115d483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061277e565b9392505050565b60005b84518110156116905760008582815181106115f557fe5b60200260200101519050600085838151811061160d57fe5b602002602001015190506000811115611686578715611660576116358a8a84600160006127aa565b6116506001600160a01b038b1683338463ffffffff61295a16565b61165b8a8386612a6c565b611686565b61166c82338c84612ba6565b6116788a838784612bfe565b6116868a8a846000806127aa565b50506001016115de565b5050505050505050565b60005b84518110156117935760008582815181106116b457fe5b6020026020010151905060008583815181106116cc57fe5b6020026020010151905060008111156117895787156117325761171382338d7f00000000000000000000000000000000000000000000000000000000000000008501612ba6565b61171f8b838784612bfe565b61172d8b8b846001806127aa565b611789565b6117418b8b84600060016127aa565b61177e6001600160a01b038c16838b7f0000000000000000000000000000000000000000000000000000000000000000850363ffffffff61295a16565b6117898b8386612a6c565b505060010161169d565b505050505050505050565b8115611909576001600160a01b03808416600081815260026020526040908190206003015490516340c10f1960e01b815291926340c10f19926117e992909116908690600401613642565b600060405180830381600087803b15801561180357600080fd5b505af1158015611817573d6000803e3d6000fd5b50505050600081111561190957826001600160a01b03166340c10f196000809054906101000a90046001600160a01b03166001600160a01b031663469048406040518163ffffffff1660e01b815260040160206040518083038186803b15801561188057600080fd5b505afa158015611894573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b89190613272565b836040518363ffffffff1660e01b81526004016118d6929190613642565b600060405180830381600087803b1580156118f057600080fd5b505af1158015611904573d6000803e3d6000fd5b505050505b505050565b6119188133612ce5565b6113105760405162461bcd60e51b81526004016103ca90613db3565b6001600160a01b0380851660009081526002602052604081206004015490911680156119c75760405163a045808360e01b81526001600160a01b0382169063a04580839061198c908990899089908990600401613744565b600060405180830381600087803b1580156119a657600080fd5b505af11580156119ba573d6000803e3d6000fd5b50505050809150506119cd565b60009150505b949350505050565b6001600160a01b038216600090815260026020908152604091829020600501805483518184028101840190945280845260609392830182828015611a4257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611a24575b50939450600093505050505b815181101561143957818181518110611a6357fe5b60200260200101516001600160a01b031663c153dd0785856040518363ffffffff1660e01b8152600401611a98929190613642565b600060405180830381600087803b158015611ab257600080fd5b505af1158015611ac6573d6000803e3d6000fd5b505060019092019150611a4e9050565b6000828201838110156115d45760405162461bcd60e51b81526004016103ca90613920565b60006115d4670de0b6b3a7640000611b19858563ffffffff612d7316565b9063ffffffff612dad16565b611b2f8282612ce5565b610b3e5760405162461bcd60e51b81526004016103ca90613db3565b600054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec90611b7b90849060040161362e565b60206040518083038186803b158015611b9357600080fd5b505afa158015611ba7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcb9190613339565b611be75760405162461bcd60e51b81526004016103ca90613d70565b611bf081612def565b6113355760405162461bcd60e51b81526004016103ca90613957565b6002604051631ade272960e11b81526001600160a01b038316906335bc4e5290611c3a90339060040161362e565b60206040518083038186803b158015611c5257600080fd5b505afa158015611c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8a919061353d565b6002811115611c9557fe5b14611cb25760405162461bcd60e51b81526004016103ca90613ac8565b6000546040516342f6e38960e01b81526001600160a01b03909116906342f6e38990611ce290339060040161362e565b60206040518083038186803b158015611cfa57600080fd5b505afa158015611d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d329190613339565b6113355760405162461bcd60e51b81526004016103ca90613d2c565b600080611db484805480602002602001604051908101604052809291908181526020018280548015611da957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d8b575b505050505084612e1e565b9150915080611dd55760405162461bcd60e51b81526004016103ca906137ac565b835460001901828114611e4757848181548110611dee57fe5b9060005260206000200160009054906101000a90046001600160a01b0316858481548110611e1857fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b84805480611e5157fe5b600082815260209020810160001990810180546001600160a01b03191690550190555050505050565b606080606080846001600160a01b03166399d50d5d6040518163ffffffff1660e01b815260040160006040518083038186803b158015611eb957600080fd5b505afa158015611ecd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ef5919081019061328e565b805190915060608167ffffffffffffffff81118015611f1357600080fd5b50604051908082528060200260200182016040528015611f3d578160200160208202803683370190505b50905060608267ffffffffffffffff81118015611f5957600080fd5b50604051908082528060200260200182016040528015611f83578160200160208202803683370190505b5090506000886001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611fc157600080fd5b505afa158015611fd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ff9919061355c565b905060005b855181101561228857600086828151811061201557fe5b6020026020010151905060006120b56120b0836001600160a01b03166370a082318f6040518263ffffffff1660e01b8152600401612053919061362e565b60206040518083038186803b15801561206b57600080fd5b505afa15801561207f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a3919061355c565b869063ffffffff612e8416565b612e96565b60405163a7bdad0360e01b81529091506000906060906001600160a01b038f169063a7bdad03906120ea90879060040161362e565b60006040518083038186803b15801561210257600080fd5b505afa158015612116573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261213e919081019061328e565b8051909150156122275760005b81518110156122255760008f6001600160a01b03166322ebeba48785858151811061217257fe5b60200260200101516040518363ffffffff1660e01b815260040161219792919061365b565b60206040518083038186803b1580156121af57600080fd5b505afa1580156121c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e7919061355c565b9050600081131561220957612202858263ffffffff612ebf16565b945061221c565b612219848263ffffffff612ebf16565b93505b5060010161214b565b505b61223083612f05565b88868151811061223c57fe5b602090810291909101015261226161225c8360001963ffffffff612f2716565b612f05565b87868151811061226d57fe5b6020908102919091010152505060019092019150611ffe9050565b50939891975095509350505050565b60008215806122a4575081155b156122b1575060006106ca565b6115d460016122e2670de0b6b3a7640000611b19836122d6898963ffffffff612d7316565b9063ffffffff61159216565b9063ffffffff611ad616565b60008054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec9061231f90859060040161362e565b60206040518083038186803b15801561233757600080fd5b505afa15801561234b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236f9190613339565b80156106ca57506040516335fc6c9f60e21b81526001600160a01b0383169063d7f1b27c906123a290309060040161362e565b60206040518083038186803b1580156123ba57600080fd5b505afa1580156123ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ca9190613339565b606080606080846001600160a01b03166399d50d5d6040518163ffffffff1660e01b815260040160006040518083038186803b15801561243157600080fd5b505afa158015612445573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261246d919081019061328e565b805190915060608167ffffffffffffffff8111801561248b57600080fd5b506040519080825280602002602001820160405280156124b5578160200160208202803683370190505b50905060608267ffffffffffffffff811180156124d157600080fd5b506040519080825280602002602001820160405280156124fb578160200160208202803683370190505b50905060005b845181101561276e57600085828151811061251857fe5b6020026020010151905060008a6001600160a01b03166366cb8d2f836040518263ffffffff1660e01b8152600401612550919061362e565b60206040518083038186803b15801561256857600080fd5b505afa15801561257c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a0919061355c565b60405163a7bdad0360e01b81529091506000906060906001600160a01b038e169063a7bdad03906125d590879060040161362e565b60006040518083038186803b1580156125ed57600080fd5b505afa158015612601573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612629919081019061328e565b8051909150156127125760005b81518110156127105760008e6001600160a01b03166322ebeba48785858151811061265d57fe5b60200260200101516040518363ffffffff1660e01b815260040161268292919061365b565b60206040518083038186803b15801561269a57600080fd5b505afa1580156126ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d2919061355c565b905060008113156126f4576126ed858263ffffffff612ebf16565b9450612707565b612704848263ffffffff612ebf16565b93505b50600101612636565b505b61271b83612f05565b87868151811061272757fe5b602090810291909101015261274761225c8360001963ffffffff612f2716565b86868151811061275357fe5b60209081029190910101525050600190920191506125019050565b5092979096509194509092505050565b600081848411156127a25760405162461bcd60e51b81526004016103ca9190613799565b505050900390565b60405163a7bdad0360e01b81526060906001600160a01b0387169063a7bdad03906127d990879060040161362e565b60006040518083038186803b1580156127f157600080fd5b505afa158015612805573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261282d919081019061328e565b805190915083156128cc5760005b818110156128c65782818151811061284f57fe5b60200260200101516001600160a01b0316630fb96b21898989886040518563ffffffff1660e01b8152600401612888949392919061376f565b600060405180830381600087803b1580156128a257600080fd5b505af11580156128b6573d6000803e3d6000fd5b50506001909201915061283b9050565b50611904565b60005b81811015611690578281815181106128e357fe5b60200260200101516001600160a01b031663c137f4d7898989886040518563ffffffff1660e01b815260040161291c949392919061376f565b600060405180830381600087803b15801561293657600080fd5b505af115801561294a573d6000803e3d6000fd5b5050600190920191506128cf9050565b80156114395760608282604051602401612975929190613642565b60408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b179052516347b7819960e11b81529091506060906001600160a01b03871690638f6f0332906129d49088906000908790600401613699565b600060405180830381600087803b1580156129ee57600080fd5b505af1158015612a02573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612a2a9190810190613355565b805190915015612a645780806020019051810190612a489190613339565b612a645760405162461bcd60e51b81526004016103ca90613812565b505050505050565b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190612a9b90879060040161362e565b60206040518083038186803b158015612ab357600080fd5b505afa158015612ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aeb919061355c565b90506000612b6e856001600160a01b03166366cb8d2f866040518263ffffffff1660e01b8152600401612b1e919061362e565b60206040518083038186803b158015612b3657600080fd5b505afa158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225c919061355c565b9050612b80838263ffffffff61229716565b821015612b9f5760405162461bcd60e51b81526004016103ca90613e34565b5050505050565b611439846323b872dd60e01b858585604051602401612bc793929190613675565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612f92565b6040516370a0823160e01b81526000906001600160a01b038516906370a0823190612c2d90889060040161362e565b60206040518083038186803b158015612c4557600080fd5b505afa158015612c59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7d919061355c565b90506000612cb0866001600160a01b03166366cb8d2f876040518263ffffffff1660e01b8152600401612b1e919061362e565b9050612cc6836122e2868463ffffffff61229716565b821015612a645760405162461bcd60e51b81526004016103ca90613a3d565b6000816001600160a01b0316836001600160a01b031663481c6a756040518163ffffffff1660e01b815260040160206040518083038186803b158015612d2a57600080fd5b505afa158015612d3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d629190613272565b6001600160a01b0316149392505050565b600082612d82575060006106ca565b82820282848281612d8f57fe5b04146115d45760405162461bcd60e51b81526004016103ca90613aff565b60006115d483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613021565b6040516353bae5f760e01b81526000906001600160a01b038316906353bae5f7906123a290309060040161362e565b81516000908190815b81811015612e7157846001600160a01b0316868281518110612e4557fe5b60200260200101516001600160a01b03161415612e6957925060019150612e7d9050565b600101612e27565b50600019600092509250505b9250929050565b60006115d4828463ffffffff61305816565b6000600160ff1b8210612ebb5760405162461bcd60e51b81526004016103ca90613ce4565b5090565b6000828201818312801590612ed45750838112155b80612ee95750600083128015612ee957508381125b6115d45760405162461bcd60e51b81526004016103ca906139fc565b600080821215612ebb5760405162461bcd60e51b81526004016103ca90613a93565b600082612f36575060006106ca565b82600019148015612f4a5750600160ff1b82145b15612f675760405162461bcd60e51b81526004016103ca90613b6f565b82820282848281612f7457fe5b05146115d45760405162461bcd60e51b81526004016103ca90613b6f565b6060612fe7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130769092919063ffffffff16565b80519091501561190957808060200190518101906130059190613339565b6119095760405162461bcd60e51b81526004016103ca90613dea565b600081836130425760405162461bcd60e51b81526004016103ca9190613799565b50600083858161304e57fe5b0495945050505050565b60006115d482611b1985670de0b6b3a764000063ffffffff612d7316565b60606119cd84846000858561308a85613120565b6130a65760405162461bcd60e51b81526004016103ca90613c76565b60006060866001600160a01b031685876040516130c39190613612565b60006040518083038185875af1925050503d8060008114613100576040519150601f19603f3d011682016040523d82523d6000602084013e613105565b606091505b5091509150613115828286613126565b979650505050505050565b3b151590565b606083156131355750816115d4565b8251156131455782518084602001fd5b8160405162461bcd60e51b81526004016103ca9190613799565b50805460008255906000526020600020908101906113359190613226565b6040518060c0016040528060008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b03168152602001606081525090565b82805482825590600052602060002090810192821561321a579160200282015b8281111561321a57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906131e5565b50612ebb929150613243565b61324091905b80821115612ebb576000815560010161322c565b90565b61324091905b80821115612ebb5780546001600160a01b0319168155600101613249565b80516106ca81613fef565b600060208284031215613283578081fd5b81516115d481613fef565b600060208083850312156132a0578182fd5b825167ffffffffffffffff808211156132b7578384fd5b81850186601f8201126132c8578485fd5b80519250818311156132d8578485fd5b83830291506132e8848301613f9c565b8381528481019082860184840187018a1015613302578788fd5b8794505b8585101561332c576133188a82613267565b835260019490940193918601918601613306565b5098975050505050505050565b60006020828403121561334a578081fd5b81516115d481614004565b600060208284031215613366578081fd5b815167ffffffffffffffff8082111561337d578283fd5b81840185601f82011261338e578384fd5b805192508183111561339e578384fd5b6133b1601f8401601f1916602001613f9c565b91508282528560208483010111156133c7578384fd5b6133d8836020840160208401613fc3565b50949350505050565b6000602082840312156133f2578081fd5b81356115d481613fef565b6000806040838503121561340f578081fd5b823561341a81613fef565b9150602083013561342a81613fef565b809150509250929050565b60008060408385031215613447578182fd5b823561345281613fef565b946020939093013593505050565b600080600060608486031215613474578081fd5b833561347f81613fef565b925060208401359150604084013561349681613fef565b809150509250925092565b6000806000606084860312156134b5578283fd5b83356134c081613fef565b925060208401359150604084013561349681614004565b60008060008060008060c087890312156134ef578182fd5b86356134fa81613fef565b9550602087013594506040870135935060608701359250608087013561351f81613fef565b915060a087013561352f81613fef565b809150509295509295509295565b60006020828403121561354e578081fd5b8151600381106115d4578182fd5b60006020828403121561356d578081fd5b5051919050565b6000815180845260208085019450808401835b838110156135ac5781516001600160a01b031687529582019590820190600101613587565b509495945050505050565b6000815180845260208085019450808401835b838110156135ac578151875295820195908201906001016135ca565b600081518084526135fe816020860160208601613fc3565b601f01601f19169290920160200192915050565b60008251613624818460208701613fc3565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060018060a01b0385168252836020830152606060408301526136c060608301846135e6565b95945050505050565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6000602082526115d46020830184613574565b6000606082526137156060830186613574565b828103602084015261372781866135b7565b838103604085015261311581866135b7565b901515815260200190565b6001600160a01b03948516815260208101939093529083166040830152909116606082015260800190565b6001600160a01b039485168152602081019390935292166040820152901515606082015260800190565b6000602082526115d460208301846135e6565b60208082526015908201527420b2323932b9b9903737ba1034b71030b93930bc9760591b604082015260600190565b6020808252601f908201527f52656465656d206665652063616e277420657863656564206d6178696d756d00604082015260600190565b602080825260159082015274115490cc8c081d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b60208082526016908201527514d85b59481c995919595b48199959481c185cdcd95960521b604082015260600190565b60208082526028908201527f4d75737420626520612076616c696420616e6420696e697469616c697a65642060408201526729b2ba2a37b5b2b760c11b606082015260800190565b60208082526016908201527526b7b23ab632903737ba103932b3b4b9ba32b932b21760511b604082015260600190565b6020808252601b908201527f52656465656d207175616e74697479206d757374206265203e20300000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601e908201527f4d7573742062652070656e64696e6720696e697469616c697a6174696f6e0000604082015260600190565b6020808252601e908201527f4973737565206665652063616e277420657863656564206d6178696d756d0000604082015260600190565b6020808252601a908201527f4973737565207175616e74697479206d757374206265203e2030000000000000604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526036908201527f496e76616c6964207472616e7366657220696e2e20526573756c747320696e206040820152753ab73232b931b7b63630ba32b930b634bd30ba34b7b760511b606082015260800190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b60208082526018908201527f4f6e6c7920746865206d6f64756c652063616e2063616c6c0000000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526015908201527414d85b59481a5cdcdd5948199959481c185cdcd959605a1b604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b60208082526022908201527f4973737565206665652063616e277420657863656564206d6178696d756d2066604082015261656560f01b606082015260800190565b60208082526019908201527f53616d652066656520726563697069656e742070617373656400000000000000604082015260600190565b60208082526027908201527f46656520526563697069656e74206d757374206265206e6f6e2d7a65726f206160408201526632323932b9b99760c91b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252601a908201527f4d6f64756c6520616c726561647920726567697374657265642e000000000000604082015260600190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b60208082526024908201527f4d6f64756c65206d75737420626520656e61626c6564206f6e20636f6e74726f604082015263363632b960e11b606082015260800190565b60208082526023908201527f4d75737420626520636f6e74726f6c6c65722d656e61626c656420536574546f60408201526235b2b760e91b606082015260800190565b6020808252601c908201527f4d7573742062652074686520536574546f6b656e206d616e6167657200000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526037908201527f496e76616c6964207472616e73666572206f75742e20526573756c747320696e60408201527f20756e646572636f6c6c61746572616c697a6174696f6e000000000000000000606082015260800190565b60208082526023908201527f52656769737465726564206d6f64756c6573206d7573742062652072656d6f7660408201526232b21760e91b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526023908201527f52656465656d206665652063616e277420657863656564206d6178696d756d2060408201526266656560e81b606082015260800190565b90815260200190565b9283526020830191909152604082015260600190565b948552602085019390935260408401919091526001600160a01b03908116606084015216608082015260a00190565b60405181810167ffffffffffffffff81118282101715613fbb57600080fd5b604052919050565b60005b83811015613fde578181015183820152602001613fc6565b838111156114395750506000910152565b6001600160a01b038116811461133557600080fd5b801515811461133557600080fdfea26469706673582212204bb7104025feb18fd01374aa5ffdd724e8b387b6b706f18d39c7a0ee218bce7664736f6c634300060a0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/set/ERC4626Oracle.json b/external/abi/set/ERC4626Oracle.json new file mode 100644 index 000000000..28883a71b --- /dev/null +++ b/external/abi/set/ERC4626Oracle.json @@ -0,0 +1,102 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC4626Oracle", + "sourceName": "contracts/protocol/integration/oracles/ERC4626Oracle.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "_vault", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_underlyingFullUnit", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_dataDescription", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "dataDescription", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "read", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "underlyingFullUnit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "vault", + "outputs": [ + { + "internalType": "contract IERC4626", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "vaultFullUnit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + } + ], + "bytecode": "0x60e06040523480156200001157600080fd5b50604051620008b7380380620008b78339810160408190526200003491620000ed565b6001600160a01b03831660805260006200004f82826200027b565b508160a08181525050826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000097573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000bd919062000347565b620000ca90600a62000488565b60c0525062000499915050565b634e487b7160e01b600052604160045260246000fd5b6000806000606084860312156200010357600080fd5b83516001600160a01b03811681146200011b57600080fd5b60208581015160408701519295509350906001600160401b03808211156200014257600080fd5b818701915087601f8301126200015757600080fd5b8151818111156200016c576200016c620000d7565b604051601f8201601f19908116603f01168101908382118183101715620001975762000197620000d7565b816040528281528a86848701011115620001b057600080fd5b600093505b82841015620001d45784840186015181850187015292850192620001b5565b60008684830101528096505050505050509250925092565b600181811c908216806200020157607f821691505b6020821081036200022257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200027657600081815260208120601f850160051c81016020861015620002515750805b601f850160051c820191505b8181101562000272578281556001016200025d565b5050505b505050565b81516001600160401b03811115620002975762000297620000d7565b620002af81620002a88454620001ec565b8462000228565b602080601f831160018114620002e75760008415620002ce5750858301515b600019600386901b1c1916600185901b17855562000272565b600085815260208120601f198616915b828110156200031857888601518255948401946001909101908401620002f7565b5085821015620003375787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156200035a57600080fd5b815160ff811681146200036c57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115620003ca578160001904821115620003ae57620003ae62000373565b80851615620003bc57918102915b93841c93908002906200038e565b509250929050565b600082620003e35750600162000482565b81620003f25750600062000482565b81600181146200040b5760028114620004165762000436565b600191505062000482565b60ff8411156200042a576200042a62000373565b50506001821b62000482565b5060208310610133831016604e8410600b84101617156200045b575081810a62000482565b62000467838362000389565b80600019048211156200047e576200047e62000373565b0290505b92915050565b60006200036c60ff841683620003d2565b60805160a05160c0516103d5620004e26000396000818160b80152818161012801526101ee015260008181609101526101ca01526000818160df015261015b01526103d56000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806357de26a41461005c57806358d65629146100775780636cf641c61461008c578063eb8dd5b6146100b3578063fbfa77cf146100da575b600080fd5b610064610119565b6040519081526020015b60405180910390f35b61007f610223565b60405161006e91906102b1565b6100647f000000000000000000000000000000000000000000000000000000000000000081565b6100647f000000000000000000000000000000000000000000000000000000000000000081565b6101017f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161006e565b6040516303d1689d60e11b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906307a2d13a90602401602060405180830381865afa1580156101a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c691906102ff565b90507f00000000000000000000000000000000000000000000000000000000000000006102137f000000000000000000000000000000000000000000000000000000000000000083610318565b61021d9190610343565b91505090565b6000805461023090610365565b80601f016020809104026020016040519081016040528092919081815260200182805461025c90610365565b80156102a95780601f1061027e576101008083540402835291602001916102a9565b820191906000526020600020905b81548152906001019060200180831161028c57829003601f168201915b505050505081565b600060208083528351808285015260005b818110156102de578581018301518582016040015282016102c2565b506000604082860101526040601f19601f8301168501019250505092915050565b60006020828403121561031157600080fd5b5051919050565b808202811582820484141761033d57634e487b7160e01b600052601160045260246000fd5b92915050565b60008261036057634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061037957607f821691505b60208210810361039957634e487b7160e01b600052602260045260246000fd5b5091905056fea264697066735822122029740a6b8475c392ae3ae307c4ad7d7946511b15450337995ae9c7bccafc37ef64736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806357de26a41461005c57806358d65629146100775780636cf641c61461008c578063eb8dd5b6146100b3578063fbfa77cf146100da575b600080fd5b610064610119565b6040519081526020015b60405180910390f35b61007f610223565b60405161006e91906102b1565b6100647f000000000000000000000000000000000000000000000000000000000000000081565b6100647f000000000000000000000000000000000000000000000000000000000000000081565b6101017f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161006e565b6040516303d1689d60e11b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906307a2d13a90602401602060405180830381865afa1580156101a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c691906102ff565b90507f00000000000000000000000000000000000000000000000000000000000000006102137f000000000000000000000000000000000000000000000000000000000000000083610318565b61021d9190610343565b91505090565b6000805461023090610365565b80601f016020809104026020016040519081016040528092919081815260200182805461025c90610365565b80156102a95780601f1061027e576101008083540402835291602001916102a9565b820191906000526020600020905b81548152906001019060200180831161028c57829003601f168201915b505050505081565b600060208083528351808285015260005b818110156102de578581018301518582016040015282016102c2565b506000604082860101526040601f19601f8301168501019250505092915050565b60006020828403121561031157600080fd5b5051919050565b808202811582820484141761033d57634e487b7160e01b600052601160045260246000fd5b92915050565b60008261036057634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061037957607f821691505b60208210810361039957634e487b7160e01b600052602260045260246000fd5b5091905056fea264697066735822122029740a6b8475c392ae3ae307c4ad7d7946511b15450337995ae9c7bccafc37ef64736f6c63430008110033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/set/OracleMock.json b/external/abi/set/OracleMock.json new file mode 100644 index 000000000..c2afc1558 --- /dev/null +++ b/external/abi/set/OracleMock.json @@ -0,0 +1,64 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "OracleMock", + "sourceName": "contracts/mocks/OracleMock.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_startingPrice", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "price", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "read", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newPrice", + "type": "uint256" + } + ], + "name": "updatePrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506040516101083803806101088339818101604052602081101561003357600080fd5b505160005560c2806100466000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c806357de26a41460415780638d6cc56d146059578063a035b1fe146075575b600080fd5b6047607b565b60408051918252519081900360200190f35b607360048036036020811015606d57600080fd5b50356081565b005b60476086565b60005490565b600055565b6000548156fea26469706673582212205c1cdbb033c8513a67e034cf473bc0e5f4fbf58809ab45e0ef983ae907fdd4f064736f6c634300060a0033", + "deployedBytecode": "0x6080604052348015600f57600080fd5b5060043610603c5760003560e01c806357de26a41460415780638d6cc56d146059578063a035b1fe146075575b600080fd5b6047607b565b60408051918252519081900360200190f35b607360048036036020811015606d57600080fd5b50356081565b005b60476086565b60005490565b600055565b6000548156fea26469706673582212205c1cdbb033c8513a67e034cf473bc0e5f4fbf58809ab45e0ef983ae907fdd4f064736f6c634300060a0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/set/PreciseUnitOracle.json b/external/abi/set/PreciseUnitOracle.json new file mode 100644 index 000000000..3d2245af8 --- /dev/null +++ b/external/abi/set/PreciseUnitOracle.json @@ -0,0 +1,50 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PreciseUnitOracle", + "sourceName": "contracts/protocol/integration/oracles/PreciseUnitOracle.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "_dataDescription", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "dataDescription", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "read", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function", + "gas": "0xa7d8c0" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506040516103583803806103588339818101604052602081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b90830190602082018581111561006857600080fd5b825164010000000081118282018810171561008257600080fd5b82525081516020918201929091019080838360005b838110156100af578181015183820152602001610097565b50505050905090810190601f1680156100dc5780820380516001836020036101000a031916815260200191505b50604052505081516100f6915060009060208401906100fd565b5050610198565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061013e57805160ff191683800117855561016b565b8280016001018555821561016b579182015b8281111561016b578251825591602001919060010190610150565b5061017792915061017b565b5090565b61019591905b808211156101775760008155600101610181565b90565b6101b1806101a76000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806357de26a41461003b57806358d6562914610055575b600080fd5b6100436100d2565b60408051918252519081900360200190f35b61005d6100e1565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561009757818101518382015260200161007f565b50505050905090810190601f1680156100c45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60006100dc61016f565b905090565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156101675780601f1061013c57610100808354040283529160200191610167565b820191906000526020600020905b81548152906001019060200180831161014a57829003601f168201915b505050505081565b670de0b6b3a76400009056fea26469706673582212209ab59efe6d709a1b1941f523fb188a5ea6954c970398ad1c459dbf1e51d026f764736f6c634300060a0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806357de26a41461003b57806358d6562914610055575b600080fd5b6100436100d2565b60408051918252519081900360200190f35b61005d6100e1565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561009757818101518382015260200161007f565b50505050905090810190601f1680156100c45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60006100dc61016f565b905090565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156101675780601f1061013c57610100808354040283529160200191610167565b820191906000526020600020905b81548152906001019060200180831161014a57829003601f168201915b505050505081565b670de0b6b3a76400009056fea26469706673582212209ab59efe6d709a1b1941f523fb188a5ea6954c970398ad1c459dbf1e51d026f764736f6c634300060a0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/set/PriceOracle.json b/external/abi/set/PriceOracle.json new file mode 100644 index 000000000..b2d189d72 --- /dev/null +++ b/external/abi/set/PriceOracle.json @@ -0,0 +1,437 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PriceOracle", + "sourceName": "contracts/protocol/PriceOracle.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IController", + "name": "_controller", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterQuoteAsset", + "type": "address" + }, + { + "internalType": "address[]", + "name": "_adapters", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_assetOnes", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_assetTwos", + "type": "address[]" + }, + { + "internalType": "contract IOracle[]", + "name": "_oracles", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_adapter", + "type": "address" + } + ], + "name": "AdapterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_adapter", + "type": "address" + } + ], + "name": "AdapterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newMasterQuote", + "type": "address" + } + ], + "name": "MasterQuoteAssetEdited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_assetOne", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_assetTwo", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_oracle", + "type": "address" + } + ], + "name": "PairAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_assetOne", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_assetTwo", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_newOracle", + "type": "address" + } + ], + "name": "PairEdited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_assetOne", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_assetTwo", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_oracle", + "type": "address" + } + ], + "name": "PairRemoved", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "adapters", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_adapter", + "type": "address" + } + ], + "name": "addAdapter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_assetOne", + "type": "address" + }, + { + "internalType": "address", + "name": "_assetTwo", + "type": "address" + }, + { + "internalType": "contract IOracle", + "name": "_oracle", + "type": "address" + } + ], + "name": "addPair", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newMasterQuoteAsset", + "type": "address" + } + ], + "name": "editMasterQuoteAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_assetOne", + "type": "address" + }, + { + "internalType": "address", + "name": "_assetTwo", + "type": "address" + }, + { + "internalType": "contract IOracle", + "name": "_oracle", + "type": "address" + } + ], + "name": "editPair", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "getAdapters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_assetOne", + "type": "address" + }, + { + "internalType": "address", + "name": "_assetTwo", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "masterQuoteAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "oracles", + "outputs": [ + { + "internalType": "contract IOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_adapter", + "type": "address" + } + ], + "name": "removeAdapter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_assetOne", + "type": "address" + }, + { + "internalType": "address", + "name": "_assetTwo", + "type": "address" + } + ], + "name": "removePair", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + } + ], + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001bca38038062001bca83398101604081905262000034916200036a565b6000620000496001600160e01b03620001d016565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180546001600160a01b038089166001600160a01b03199283161790925560038054928816929091169190911790558351620000d8906004906020870190620001d5565b5081518351148015620000ec575080518251145b620001145760405162461bcd60e51b81526004016200010b9062000445565b60405180910390fd5b60005b8351811015620001c3578181815181106200012e57fe5b6020026020010151600260008684815181106200014757fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008584815181106200017e57fe5b6020908102919091018101516001600160a01b0390811683529082019290925260400160002080546001600160a01b0319169290911691909117905560010162000117565b50505050505050620004dc565b335b90565b8280548282559060005260206000209081019282156200022d579160200282015b828111156200022d57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620001f6565b506200023b9291506200023f565b5090565b620001d291905b808211156200023b5780546001600160a01b031916815560010162000246565b80516200027381620004c3565b92915050565b600082601f8301126200028a578081fd5b8151620002a16200029b82620004a3565b6200047c565b818152915060208083019084810181840286018201871015620002c357600080fd5b60005b84811015620002ef578151620002dc81620004c3565b84529282019290820190600101620002c6565b505050505092915050565b600082601f8301126200030b578081fd5b81516200031c6200029b82620004a3565b8181529150602080830190848101818402860182018710156200033e57600080fd5b60005b84811015620002ef5781516200035781620004c3565b8452928201929082019060010162000341565b60008060008060008060c0878903121562000383578182fd5b6200038f888862000266565b9550620003a0886020890162000266565b60408801519095506001600160401b0380821115620003bd578384fd5b620003cb8a838b0162000279565b95506060890151915080821115620003e1578384fd5b620003ef8a838b0162000279565b9450608089015191508082111562000405578384fd5b620004138a838b0162000279565b935060a089015191508082111562000429578283fd5b506200043889828a01620002fa565b9150509295509295509295565b6020808252601b908201527f4172726179206c656e6774687320646f206e6f74206d617463682e0000000000604082015260600190565b6040518181016001600160401b03811182821017156200049b57600080fd5b604052919050565b60006001600160401b03821115620004b9578081fd5b5060209081020190565b6001600160a01b0381168114620004d957600080fd5b50565b6116de80620004ec6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806361d5b14411610097578063b82e16e311610066578063b82e16e3146101cf578063f1ec23cf146101e4578063f2fde38b146101f7578063f77c47911461020a576100f5565b806361d5b1441461018c578063715018a61461019f5780638da5cb5b146101a7578063ac41865a146101af576100f5565b806352a03c03116100d357806352a03c0314610140578063585cd34b146101535780635861b2271461016657806360d54d4114610179576100f5565b806304289853146100fa578063342833541461010f5780634ef501ac1461012d575b600080fd5b61010d6101083660046111b3565b610212565b005b61011761030d565b604051610124919061127e565b60405180910390f35b61011761013b36600461124e565b61031c565b61011761014e36600461117b565b610343565b61010d61016136600461115f565b610369565b61010d61017436600461117b565b6104e3565b61010d61018736600461115f565b6105ca565b61010d61019a36600461115f565b610702565b61010d610782565b610117610801565b6101c26101bd36600461117b565b610811565b6040516101249190611687565b6101d7610911565b60405161012491906112ac565b61010d6101f23660046111b3565b610973565b61010d61020536600461115f565b610a59565b610117610b0f565b61021a610b1e565b6000546001600160a01b039081169116146102505760405162461bcd60e51b8152600401610247906115be565b60405180910390fd5b6001600160a01b0383811660009081526002602090815260408083208685168452909152902054166102945760405162461bcd60e51b8152600401610247906115f3565b6001600160a01b03838116600081815260026020908152604080832087861680855292529182902080546001600160a01b03191694861694909417909355517f31639ce2bfc7c00ec8297cb6df66924b38918a7417c8e6b10eb7dc9f958389109061030090859061127e565b60405180910390a3505050565b6003546001600160a01b031681565b6004818154811061032957fe5b6000918252602090912001546001600160a01b0316905081565b60026020908152600092835260408084209091529082529020546001600160a01b031681565b610371610b1e565b6000546001600160a01b0390811691161461039e5760405162461bcd60e51b8152600401610247906115be565b61040b8160048054806020026020016040519081016040528092919081815260200182805480156103f857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116103da575b5050505050610b2290919063ffffffff16565b6104275760405162461bcd60e51b8152600401610247906113f8565b61049481600480548060200260200160405190810160405280929190818152602001828054801561048157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610463575b5050505050610b3890919063ffffffff16565b80516104a8916004916020909101906110d6565b507fdf980d21d8c7bb34800e668dbe003299093bac8e693614151d3c57f73f98a93d816040516104d8919061127e565b60405180910390a150565b6104eb610b1e565b6000546001600160a01b039081169116146105185760405162461bcd60e51b8152600401610247906115be565b6001600160a01b03828116600090815260026020908152604080832085851684529091529020541661055c5760405162461bcd60e51b81526004016102479061163c565b6001600160a01b03828116600081815260026020908152604080832086861680855292529182902080546001600160a01b031981169091559151919093169291907fd9001d4fd555e50f50619eeca8a260400b5e944989042d0652c5834aa2b968609061030090859061127e565b6105d2610b1e565b6000546001600160a01b039081169116146105ff5760405162461bcd60e51b8152600401610247906115be565b61066a8160048054806020026020016040519081016040528092919081815260200182805480156103f8576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116103da575050505050610b2290919063ffffffff16565b156106875760405162461bcd60e51b8152600401610247906114d9565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b0383161790556040517fcf9c2c7f9adbb156bd76affb04df84595f8f5e69cab2e61221b05b05a902fa26906104d890839061127e565b61070a610b1e565b6000546001600160a01b039081169116146107375760405162461bcd60e51b8152600401610247906115be565b600380546001600160a01b0319166001600160a01b0383161790556040517f748818fcd84486bc2804c035b8dec2300489b070a39a4a290d8311cd9791d867906104d890839061127e565b61078a610b1e565b6000546001600160a01b039081169116146107b75760405162461bcd60e51b8152600401610247906115be565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b03165b90565b6001546040516313bc6d4b60e01b81526000916001600160a01b0316906313bc6d4b9061084290339060040161127e565b60206040518083038186803b15801561085a57600080fd5b505afa15801561086e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089291906111fd565b6108ae5760405162461bcd60e51b815260040161024790611528565b6000806108bb8585610b80565b9092509050816108d5576108cf8585610c8f565b90925090505b816108ea576108e48585610cf5565b90925090505b816109075760405162461bcd60e51b81526004016102479061144a565b9150505b92915050565b6060600480548060200260200160405190810160405280929190818152602001828054801561096957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161094b575b5050505050905090565b61097b610b1e565b6000546001600160a01b039081169116146109a85760405162461bcd60e51b8152600401610247906115be565b6001600160a01b038381166000908152600260209081526040808320868516845290915290205416156109ed5760405162461bcd60e51b815260040161024790611490565b6001600160a01b03838116600081815260026020908152604080832087861680855292529182902080546001600160a01b03191694861694909417909355517f7f46075c67ca5bbd3aaf82d8e324282141f27b7cba3376e5498a6b70c9931c2a9061030090859061127e565b610a61610b1e565b6000546001600160a01b03908116911614610a8e5760405162461bcd60e51b8152600401610247906115be565b6001600160a01b038116610ab45760405162461bcd60e51b8152600401610247906113b2565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b3390565b600080610b2f8484610dcb565b95945050505050565b6060600080610b478585610dcb565b9150915080610b685760405162461bcd60e51b81526004016102479061134c565b6060610b748684610e2e565b50935061090b92505050565b6001600160a01b038083166000908152600260209081526040808320858516845290915281205490918291168015801590610c33576001826001600160a01b03166357de26a46040518163ffffffff1660e01b815260040160206040518083038186803b158015610bf057600080fd5b505afa158015610c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c289190611266565b935093505050610c88565b6001600160a01b0380861660009081526002602090815260408083208a85168452909152902054168015801590610c7c576001610c6f83610f5d565b9550955050505050610c88565b50600094508493505050505b9250929050565b600354600090819081908190610caf9087906001600160a01b0316610b80565b60035491935091506000908190610cd09088906001600160a01b0316610b80565b91509150838015610cde5750815b15610c7c576001610c6f848363ffffffff610ff216565b600080805b600454811015610dbe5760008060048381548110610d1457fe5b600091825260209091200154604051635620c32d60e11b81526001600160a01b039091169063ac41865a90610d4f908a908a90600401611292565b604080518083038186803b158015610d6657600080fd5b505afa158015610d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9e919061121d565b915091508115610db4579093509150610c889050565b5050600101610cfa565b5060009485945092505050565b81516000908190815b81811015610e1e57846001600160a01b0316868281518110610df257fe5b60200260200101516001600160a01b03161415610e1657925060019150610c889050565b600101610dd4565b5060001995600095509350505050565b8151606090600090808410610e555760405162461bcd60e51b81526004016102479061137b565b60606001820367ffffffffffffffff81118015610e7157600080fd5b50604051908082528060200260200182016040528015610e9b578160200160208202803683370190505b50905060005b85811015610ee957868181518110610eb557fe5b6020026020010151828281518110610ec957fe5b6001600160a01b0390921660209283029190910190910152600101610ea1565b50600185015b82811015610f3a57868181518110610f0357fe5b6020026020010151826001830381518110610f1a57fe5b6001600160a01b0390921660209283029190910190910152600101610eef565b5080868681518110610f4857fe5b60200260200101519350935050509250929050565b600080826001600160a01b03166357de26a46040518163ffffffff1660e01b815260040160206040518083038186803b158015610f9957600080fd5b505afa158015610fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd19190611266565b9050610feb81610fdf61101c565b9063ffffffff610ff216565b9392505050565b6000610feb8261101085670de0b6b3a764000063ffffffff61102816565b9063ffffffff61106216565b670de0b6b3a764000090565b6000826110375750600061090b565b8282028284828161104457fe5b0414610feb5760405162461bcd60e51b81526004016102479061157d565b6000610feb83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250600081836110c05760405162461bcd60e51b815260040161024791906112f9565b5060008385816110cc57fe5b0495945050505050565b82805482825590600052602060002090810192821561112b579160200282015b8281111561112b57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906110f6565b5061113792915061113b565b5090565b61080e91905b808211156111375780546001600160a01b0319168155600101611141565b600060208284031215611170578081fd5b8135610feb81611690565b6000806040838503121561118d578081fd5b823561119881611690565b915060208301356111a881611690565b809150509250929050565b6000806000606084860312156111c7578081fd5b83356111d281611690565b925060208401356111e281611690565b915060408401356111f281611690565b809150509250925092565b60006020828403121561120e578081fd5b81518015158114610feb578182fd5b6000806040838503121561122f578182fd5b8251801515811461123e578283fd5b6020939093015192949293505050565b60006020828403121561125f578081fd5b5035919050565b600060208284031215611277578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6020808252825182820181905260009190848201906040850190845b818110156112ed5783516001600160a01b0316835292840192918401916001016112c8565b50909695505050505050565b6000602080835283518082850152825b8181101561132557858101830151858201604001528201611309565b818111156113365783604083870101525b50601f01601f1916929092016040019392505050565b60208082526015908201527420b2323932b9b9903737ba1034b71030b93930bc9760591b604082015260600190565b60208082526018908201527f496e646578206d757374206265203c2041206c656e6774680000000000000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526032908201527f50726963654f7261636c652e72656d6f7665416461707465723a20416461707460408201527132b9103237b2b9903737ba1032bc34b9ba1760711b606082015260800190565b60208082526026908201527f50726963654f7261636c652e67657450726963653a205072696365206e6f74206040820152653337bab7321760d11b606082015260800190565b60208082526029908201527f50726963654f7261636c652e616464506169723a205061697220616c726561646040820152683c9032bc34b9ba399760b91b606082015260800190565b6020808252602f908201527f50726963654f7261636c652e616464416461707465723a20416461707465722060408201526e30b63932b0b23c9032bc34b9ba399760891b606082015260800190565b60208082526035908201527f50726963654f7261636c652e67657450726963653a2043616c6c6572206d75736040820152743a1031329039bcb9ba32b69031b7b73a3930b1ba1760591b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f50726963654f7261636c652e65646974506169723a205061697220646f65736e60408201526813ba1032bc34b9ba1760b91b606082015260800190565b6020808252602b908201527f50726963654f7261636c652e72656d6f7665506169723a205061697220646f6560408201526a39b713ba1032bc34b9ba1760a91b606082015260800190565b90815260200190565b6001600160a01b03811681146116a557600080fd5b5056fea2646970667358221220aadc8c8be681b3e8e74ab5459ec39630bbdf4b6fdffac2e39e53b80582d85d6064736f6c634300060a0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806361d5b14411610097578063b82e16e311610066578063b82e16e3146101cf578063f1ec23cf146101e4578063f2fde38b146101f7578063f77c47911461020a576100f5565b806361d5b1441461018c578063715018a61461019f5780638da5cb5b146101a7578063ac41865a146101af576100f5565b806352a03c03116100d357806352a03c0314610140578063585cd34b146101535780635861b2271461016657806360d54d4114610179576100f5565b806304289853146100fa578063342833541461010f5780634ef501ac1461012d575b600080fd5b61010d6101083660046111b3565b610212565b005b61011761030d565b604051610124919061127e565b60405180910390f35b61011761013b36600461124e565b61031c565b61011761014e36600461117b565b610343565b61010d61016136600461115f565b610369565b61010d61017436600461117b565b6104e3565b61010d61018736600461115f565b6105ca565b61010d61019a36600461115f565b610702565b61010d610782565b610117610801565b6101c26101bd36600461117b565b610811565b6040516101249190611687565b6101d7610911565b60405161012491906112ac565b61010d6101f23660046111b3565b610973565b61010d61020536600461115f565b610a59565b610117610b0f565b61021a610b1e565b6000546001600160a01b039081169116146102505760405162461bcd60e51b8152600401610247906115be565b60405180910390fd5b6001600160a01b0383811660009081526002602090815260408083208685168452909152902054166102945760405162461bcd60e51b8152600401610247906115f3565b6001600160a01b03838116600081815260026020908152604080832087861680855292529182902080546001600160a01b03191694861694909417909355517f31639ce2bfc7c00ec8297cb6df66924b38918a7417c8e6b10eb7dc9f958389109061030090859061127e565b60405180910390a3505050565b6003546001600160a01b031681565b6004818154811061032957fe5b6000918252602090912001546001600160a01b0316905081565b60026020908152600092835260408084209091529082529020546001600160a01b031681565b610371610b1e565b6000546001600160a01b0390811691161461039e5760405162461bcd60e51b8152600401610247906115be565b61040b8160048054806020026020016040519081016040528092919081815260200182805480156103f857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116103da575b5050505050610b2290919063ffffffff16565b6104275760405162461bcd60e51b8152600401610247906113f8565b61049481600480548060200260200160405190810160405280929190818152602001828054801561048157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610463575b5050505050610b3890919063ffffffff16565b80516104a8916004916020909101906110d6565b507fdf980d21d8c7bb34800e668dbe003299093bac8e693614151d3c57f73f98a93d816040516104d8919061127e565b60405180910390a150565b6104eb610b1e565b6000546001600160a01b039081169116146105185760405162461bcd60e51b8152600401610247906115be565b6001600160a01b03828116600090815260026020908152604080832085851684529091529020541661055c5760405162461bcd60e51b81526004016102479061163c565b6001600160a01b03828116600081815260026020908152604080832086861680855292529182902080546001600160a01b031981169091559151919093169291907fd9001d4fd555e50f50619eeca8a260400b5e944989042d0652c5834aa2b968609061030090859061127e565b6105d2610b1e565b6000546001600160a01b039081169116146105ff5760405162461bcd60e51b8152600401610247906115be565b61066a8160048054806020026020016040519081016040528092919081815260200182805480156103f8576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116103da575050505050610b2290919063ffffffff16565b156106875760405162461bcd60e51b8152600401610247906114d9565b600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b0383161790556040517fcf9c2c7f9adbb156bd76affb04df84595f8f5e69cab2e61221b05b05a902fa26906104d890839061127e565b61070a610b1e565b6000546001600160a01b039081169116146107375760405162461bcd60e51b8152600401610247906115be565b600380546001600160a01b0319166001600160a01b0383161790556040517f748818fcd84486bc2804c035b8dec2300489b070a39a4a290d8311cd9791d867906104d890839061127e565b61078a610b1e565b6000546001600160a01b039081169116146107b75760405162461bcd60e51b8152600401610247906115be565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b03165b90565b6001546040516313bc6d4b60e01b81526000916001600160a01b0316906313bc6d4b9061084290339060040161127e565b60206040518083038186803b15801561085a57600080fd5b505afa15801561086e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089291906111fd565b6108ae5760405162461bcd60e51b815260040161024790611528565b6000806108bb8585610b80565b9092509050816108d5576108cf8585610c8f565b90925090505b816108ea576108e48585610cf5565b90925090505b816109075760405162461bcd60e51b81526004016102479061144a565b9150505b92915050565b6060600480548060200260200160405190810160405280929190818152602001828054801561096957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161094b575b5050505050905090565b61097b610b1e565b6000546001600160a01b039081169116146109a85760405162461bcd60e51b8152600401610247906115be565b6001600160a01b038381166000908152600260209081526040808320868516845290915290205416156109ed5760405162461bcd60e51b815260040161024790611490565b6001600160a01b03838116600081815260026020908152604080832087861680855292529182902080546001600160a01b03191694861694909417909355517f7f46075c67ca5bbd3aaf82d8e324282141f27b7cba3376e5498a6b70c9931c2a9061030090859061127e565b610a61610b1e565b6000546001600160a01b03908116911614610a8e5760405162461bcd60e51b8152600401610247906115be565b6001600160a01b038116610ab45760405162461bcd60e51b8152600401610247906113b2565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b3390565b600080610b2f8484610dcb565b95945050505050565b6060600080610b478585610dcb565b9150915080610b685760405162461bcd60e51b81526004016102479061134c565b6060610b748684610e2e565b50935061090b92505050565b6001600160a01b038083166000908152600260209081526040808320858516845290915281205490918291168015801590610c33576001826001600160a01b03166357de26a46040518163ffffffff1660e01b815260040160206040518083038186803b158015610bf057600080fd5b505afa158015610c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c289190611266565b935093505050610c88565b6001600160a01b0380861660009081526002602090815260408083208a85168452909152902054168015801590610c7c576001610c6f83610f5d565b9550955050505050610c88565b50600094508493505050505b9250929050565b600354600090819081908190610caf9087906001600160a01b0316610b80565b60035491935091506000908190610cd09088906001600160a01b0316610b80565b91509150838015610cde5750815b15610c7c576001610c6f848363ffffffff610ff216565b600080805b600454811015610dbe5760008060048381548110610d1457fe5b600091825260209091200154604051635620c32d60e11b81526001600160a01b039091169063ac41865a90610d4f908a908a90600401611292565b604080518083038186803b158015610d6657600080fd5b505afa158015610d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9e919061121d565b915091508115610db4579093509150610c889050565b5050600101610cfa565b5060009485945092505050565b81516000908190815b81811015610e1e57846001600160a01b0316868281518110610df257fe5b60200260200101516001600160a01b03161415610e1657925060019150610c889050565b600101610dd4565b5060001995600095509350505050565b8151606090600090808410610e555760405162461bcd60e51b81526004016102479061137b565b60606001820367ffffffffffffffff81118015610e7157600080fd5b50604051908082528060200260200182016040528015610e9b578160200160208202803683370190505b50905060005b85811015610ee957868181518110610eb557fe5b6020026020010151828281518110610ec957fe5b6001600160a01b0390921660209283029190910190910152600101610ea1565b50600185015b82811015610f3a57868181518110610f0357fe5b6020026020010151826001830381518110610f1a57fe5b6001600160a01b0390921660209283029190910190910152600101610eef565b5080868681518110610f4857fe5b60200260200101519350935050509250929050565b600080826001600160a01b03166357de26a46040518163ffffffff1660e01b815260040160206040518083038186803b158015610f9957600080fd5b505afa158015610fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd19190611266565b9050610feb81610fdf61101c565b9063ffffffff610ff216565b9392505050565b6000610feb8261101085670de0b6b3a764000063ffffffff61102816565b9063ffffffff61106216565b670de0b6b3a764000090565b6000826110375750600061090b565b8282028284828161104457fe5b0414610feb5760405162461bcd60e51b81526004016102479061157d565b6000610feb83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250600081836110c05760405162461bcd60e51b815260040161024791906112f9565b5060008385816110cc57fe5b0495945050505050565b82805482825590600052602060002090810192821561112b579160200282015b8281111561112b57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906110f6565b5061113792915061113b565b5090565b61080e91905b808211156111375780546001600160a01b0319168155600101611141565b600060208284031215611170578081fd5b8135610feb81611690565b6000806040838503121561118d578081fd5b823561119881611690565b915060208301356111a881611690565b809150509250929050565b6000806000606084860312156111c7578081fd5b83356111d281611690565b925060208401356111e281611690565b915060408401356111f281611690565b809150509250925092565b60006020828403121561120e578081fd5b81518015158114610feb578182fd5b6000806040838503121561122f578182fd5b8251801515811461123e578283fd5b6020939093015192949293505050565b60006020828403121561125f578081fd5b5035919050565b600060208284031215611277578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6020808252825182820181905260009190848201906040850190845b818110156112ed5783516001600160a01b0316835292840192918401916001016112c8565b50909695505050505050565b6000602080835283518082850152825b8181101561132557858101830151858201604001528201611309565b818111156113365783604083870101525b50601f01601f1916929092016040019392505050565b60208082526015908201527420b2323932b9b9903737ba1034b71030b93930bc9760591b604082015260600190565b60208082526018908201527f496e646578206d757374206265203c2041206c656e6774680000000000000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526032908201527f50726963654f7261636c652e72656d6f7665416461707465723a20416461707460408201527132b9103237b2b9903737ba1032bc34b9ba1760711b606082015260800190565b60208082526026908201527f50726963654f7261636c652e67657450726963653a205072696365206e6f74206040820152653337bab7321760d11b606082015260800190565b60208082526029908201527f50726963654f7261636c652e616464506169723a205061697220616c726561646040820152683c9032bc34b9ba399760b91b606082015260800190565b6020808252602f908201527f50726963654f7261636c652e616464416461707465723a20416461707465722060408201526e30b63932b0b23c9032bc34b9ba399760891b606082015260800190565b60208082526035908201527f50726963654f7261636c652e67657450726963653a2043616c6c6572206d75736040820152743a1031329039bcb9ba32b69031b7b73a3930b1ba1760591b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f50726963654f7261636c652e65646974506169723a205061697220646f65736e60408201526813ba1032bc34b9ba1760b91b606082015260800190565b6020808252602b908201527f50726963654f7261636c652e72656d6f7665506169723a205061697220646f6560408201526a39b713ba1032bc34b9ba1760a91b606082015260800190565b90815260200190565b6001600160a01b03811681146116a557600080fd5b5056fea2646970667358221220aadc8c8be681b3e8e74ab5459ec39630bbdf4b6fdffac2e39e53b80582d85d6064736f6c634300060a0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/set/RebasingComponentModule.json b/external/abi/set/RebasingComponentModule.json new file mode 100644 index 000000000..79825ba8a --- /dev/null +++ b/external/abi/set/RebasingComponentModule.json @@ -0,0 +1,418 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RebasingComponentModule", + "sourceName": "contracts/protocol/modules/v1/RebasingComponentModule.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IController", + "name": "_controller", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "bool", + "name": "_isAdded", + "type": "bool" + }, + { + "indexed": false, + "internalType": "contract IERC20[]", + "name": "_components", + "type": "address[]" + } + ], + "name": "RebasingComponentsUpdated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "contract IERC20[]", + "name": "_newRebasingComponents", + "type": "address[]" + } + ], + "name": "addRebasingComponents", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "name": "componentIssueHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "name": "componentRedeemHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + } + ], + "name": "getRebasingComponents", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "contract IERC20[]", + "name": "_rebasingComponents", + "type": "address[]" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "invokePreIssueHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "invokePreRedeemHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "moduleIssueHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "moduleRedeemHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "name": "rebasingComponentEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "contract IDebtIssuanceModule", + "name": "_debtIssuanceModule", + "type": "address" + } + ], + "name": "registerToModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "removeModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "contract IERC20[]", + "name": "_rebasingComponents", + "type": "address[]" + } + ], + "name": "removeRebasingComponents", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + } + ], + "name": "sync", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": "0xa7d8c0" + } + ], + "bytecode": "0x60806040523480156200001157600080fd5b506040516200211a3803806200211a8339810160408190526200003491620000b6565b600080546001600160a01b0319166001600160a01b038316178155600180556200005d620000b2565b600280546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35050620000e6565b3390565b600060208284031215620000c8578081fd5b81516001600160a01b0381168114620000df578182fd5b9392505050565b61202480620000f66000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c8063946d9204116100a2578063c153dd0711610071578063c153dd071461016c578063d002630114610203578063f2fde38b14610223578063f77c479114610236578063fb42e7ec1461023e57610116565b8063946d9204146101ca5780639b19c2bf146101dd578063a5841194146101f0578063c137f4d71461011b57610116565b80635b136512116100e95780635b1365121461017f57806366c8d1f814610192578063715018a6146101a5578063847ef08d146101ad5780638da5cb5b146101b557610116565b80630fb96b211461011b5780632d49104a1461013057806335c2b333146101595780633fe6106b1461016c575b600080fd5b61012e610129366004611a6b565b610251565b005b61014361013e3660046117a9565b610262565b6040516101509190611b16565b60405180910390f35b61012e610167366004611905565b6102d8565b61012e61017a3660046119ee565b6102f1565b61012e61018d3660046119b6565b610304565b61012e6101a0366004611905565b610412565b61012e610526565b61012e6105a5565b6101bd6107a0565b6040516101509190611ae9565b61012e6101d8366004611905565b6107b0565b61012e6101eb366004611a19565b610924565b61012e6101fe3660046117a9565b610933565b6102166102113660046119b6565b610bc7565b6040516101509190611b63565b61012e6102313660046117a9565b610be7565b6101bd610c9e565b61012e61024c36600461189e565b610cad565b8361025b81610cc0565b5050505050565b6001600160a01b0381166000908152600460209081526040918290208054835181840281018401909452808452606093928301828280156102cc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102ae575b50505050509050919050565b816102e281610e05565b6102ec8383610e50565b505050565b816102fb81610cc0565b6102ec83610933565b8161030e81610e05565b6040516335fc6c9f60e21b81526001600160a01b0384169063d7f1b27c9061033a908590600401611ae9565b60206040518083038186803b15801561035257600080fd5b505afa158015610366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038a9190611882565b6103af5760405162461bcd60e51b81526004016103a690611d21565b60405180910390fd5b6040516306cd8db760e51b81526001600160a01b0383169063d9b1b6e0906103db908690600401611ae9565b600060405180830381600087803b1580156103f557600080fd5b505af1158015610409573d6000803e3d6000fd5b50505050505050565b8161041c81610e05565b60005b82518110156104db57600083828151811061043657fe5b6020908102919091018101516001600160a01b0380881660009081526003845260408082209284168252919093529091205490915060ff1661048a5760405162461bcd60e51b81526004016103a690611f4d565b6001600160a01b0380861660008181526003602090815260408083209486168352938152838220805460ff191690559181526004909152206104d2908263ffffffff610f7216565b5060010161041f565b5060001515836001600160a01b03167f4350523f9d22b1cba0809180a64bb309a4840366d65bcea72c1316cfa80528ac846040516105199190611b16565b60405180910390a3505050565b61052e61109e565b6002546001600160a01b0390811691161461055b5760405162461bcd60e51b81526004016103a690611ddb565b6002546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600280546001600160a01b0319169055565b336105af81610e2b565b336105b981610933565b6001600160a01b03811660009081526004602090815260409182902080548351818402810184019094528084526060939283018282801561062357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610605575b50939450600093505050505b815181101561068657600082828151811061064657fe5b6020908102919091018101516001600160a01b03808716600090815260038452604080822092909316815292529020805460ff191690555060010161062f565b506001600160a01b03821660009081526004602052604081206106a891611776565b6060826001600160a01b031663b2494df36040518163ffffffff1660e01b815260040160006040518083038186803b1580156106e357600080fd5b505afa1580156106f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261071f91908101906117e1565b905060005b815181101561025b5781818151811061073957fe5b60200260200101516001600160a01b031663e0799620856040518263ffffffff1660e01b815260040161076c9190611ae9565b600060405180830381600087803b15801561078657600080fd5b505af1925050508015610797575060015b50600101610724565b6002546001600160a01b03165b90565b81336107bc82826110a2565b836107c6816110cc565b846001600160a01b0316630ffe0f1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561080157600080fd5b505af1158015610815573d6000803e3d6000fd5b505050506060856001600160a01b031663b2494df36040518163ffffffff1660e01b815260040160006040518083038186803b15801561085457600080fd5b505afa158015610868573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261089091908101906117e1565b905060005b8151811015610911578181815181106108aa57fe5b60200260200101516001600160a01b031663d9b1b6e0886040518263ffffffff1660e01b81526004016108dd9190611ae9565b600060405180830381600087803b1580156108f757600080fd5b505af1925050508015610908575060015b50600101610895565b5061091c8686610e50565b505050505050565b8361092e81610cc0565b61025b855b600260015414156109565760405162461bcd60e51b81526004016103a690611f16565b60026001558061096581610e2b565b6000826001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109a057600080fd5b505afa1580156109b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d89190611ad1565b90508015610bbe576001600160a01b038316600090815260046020908152604091829020805483518184028101840190945280845260609392830182828015610a4a57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a2c575b50939450600093505050505b8151811015610bbb576000828281518110610a6d57fe5b602002602001015190506000610afd876001600160a01b03166366cb8d2f846040518263ffffffff1660e01b8152600401610aa89190611ae9565b60206040518083038186803b158015610ac057600080fd5b505afa158015610ad4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af89190611ad1565b61118d565b90506000610b8d86846001600160a01b03166370a082318b6040518263ffffffff1660e01b8152600401610b319190611ae9565b60206040518083038186803b158015610b4957600080fd5b505afa158015610b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b819190611ad1565b9063ffffffff6111b316565b9050808214610bb057610bb06001600160a01b038916848363ffffffff6111e616565b505050600101610a56565b50505b50506001805550565b600360209081526000928352604080842090915290825290205460ff1681565b610bef61109e565b6002546001600160a01b03908116911614610c1c5760405162461bcd60e51b81526004016103a690611ddb565b6001600160a01b038116610c425760405162461bcd60e51b81526004016103a690611c38565b6002546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031681565b84610cb781610cc0565b61091c86610933565b6002604051631ade272960e11b81526001600160a01b038316906335bc4e5290610cee903390600401611ae9565b60206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190611ab2565b6002811115610d4957fe5b14610d665760405162461bcd60e51b81526004016103a690611cea565b6000546040516342f6e38960e01b81526001600160a01b03909116906342f6e38990610d96903390600401611ae9565b60206040518083038186803b158015610dae57600080fd5b505afa158015610dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de69190611882565b610e025760405162461bcd60e51b81526004016103a690611e58565b50565b610e0f8133611364565b610e2b5760405162461bcd60e51b81526004016103a690611edf565b610e34816113f2565b610e025760405162461bcd60e51b81526004016103a690611bf0565b60005b8151811015610f28576000828281518110610e6a57fe5b6020908102919091018101516001600160a01b0380871660009081526003845260408082209284168252919093529091205490915060ff1615610ebf5760405162461bcd60e51b81526004016103a690611d58565b6001600160a01b03808516600081815260036020908152604080832095909416808352948152838220805460ff19166001908117909155928252600481529281208054808401825590825292902090910180546001600160a01b03191690921790915501610e53565b5060011515826001600160a01b03167f4350523f9d22b1cba0809180a64bb309a4840366d65bcea72c1316cfa80528ac83604051610f669190611b16565b60405180910390a35050565b600080610fd884805480602002602001604051908101604052809291908181526020018280548015610fcd57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610faf575b5050505050846114f6565b9150915080610ff95760405162461bcd60e51b81526004016103a690611bc1565b83546000190182811461106b5784818154811061101257fe5b9060005260206000200160009054906101000a90046001600160a01b031685848154811061103c57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b8480548061107557fe5b600082815260209020810160001990810180546001600160a01b03191690550190555050505050565b3390565b6110ac8282611364565b6110c85760405162461bcd60e51b81526004016103a690611edf565b5050565b600054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec906110fc908490600401611ae9565b60206040518083038186803b15801561111457600080fd5b505afa158015611128573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114c9190611882565b6111685760405162461bcd60e51b81526004016103a690611e9c565b6111718161155c565b610e025760405162461bcd60e51b81526004016103a690611c7e565b6000808212156111af5760405162461bcd60e51b81526004016103a690611cb5565b5090565b60006111dd826111d185670de0b6b3a764000063ffffffff61158b16565b9063ffffffff6115c516565b90505b92915050565b60006111f28484611607565b9050801580156112025750600082115b1561127957611211848461168e565b611274576040516304e3532760e41b81526001600160a01b03851690634e35327090611241908690600401611ae9565b600060405180830381600087803b15801561125b57600080fd5b505af115801561126f573d6000803e3d6000fd5b505050505b6112f6565b808015611284575081155b156112f657611293848461168e565b6112f657604051636f86c89760e01b81526001600160a01b03851690636f86c897906112c3908690600401611ae9565b600060405180830381600087803b1580156112dd57600080fd5b505af11580156112f1573d6000803e3d6000fd5b505050505b836001600160a01b0316632ba57d178461130f8561171a565b6040518363ffffffff1660e01b815260040161132c929190611afd565b600060405180830381600087803b15801561134657600080fd5b505af115801561135a573d6000803e3d6000fd5b5050505050505050565b6000816001600160a01b0316836001600160a01b031663481c6a756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113a957600080fd5b505afa1580156113bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e191906117c5565b6001600160a01b0316149392505050565b60008054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec90611423908590600401611ae9565b60206040518083038186803b15801561143b57600080fd5b505afa15801561144f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114739190611882565b80156111e057506040516335fc6c9f60e21b81526001600160a01b0383169063d7f1b27c906114a6903090600401611ae9565b60206040518083038186803b1580156114be57600080fd5b505afa1580156114d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e09190611882565b81516000908190815b8181101561154957846001600160a01b031686828151811061151d57fe5b60200260200101516001600160a01b03161415611541579250600191506115559050565b6001016114ff565b50600019600092509250505b9250929050565b6040516353bae5f760e01b81526000906001600160a01b038316906353bae5f7906114a6903090600401611ae9565b60008261159a575060006111e0565b828202828482816115a757fe5b04146111dd5760405162461bcd60e51b81526004016103a690611d9a565b60006111dd83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061173f565b600080836001600160a01b03166366cb8d2f846040518263ffffffff1660e01b81526004016116369190611ae9565b60206040518083038186803b15801561164e57600080fd5b505afa158015611662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116869190611ad1565b139392505050565b600080836001600160a01b031663a7bdad03846040518263ffffffff1660e01b81526004016116bd9190611ae9565b60006040518083038186803b1580156116d557600080fd5b505afa1580156116e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261171191908101906117e1565b51119392505050565b6000600160ff1b82106111af5760405162461bcd60e51b81526004016103a690611e10565b600081836117605760405162461bcd60e51b81526004016103a69190611b6e565b50600083858161176c57fe5b0495945050505050565b5080546000825590600052602060002090810190610e0291906107ad91905b808211156111af5760008155600101611795565b6000602082840312156117ba578081fd5b81356111dd81611fcb565b6000602082840312156117d6578081fd5b81516111dd81611fcb565b600060208083850312156117f3578182fd5b825167ffffffffffffffff811115611809578283fd5b80840185601f82011261181a578384fd5b8051915061182f61182a83611fab565b611f84565b828152838101908285018585028401860189101561184b578687fd5b8693505b8484101561187657805161186281611fcb565b83526001939093019291850191850161184f565b50979650505050505050565b600060208284031215611893578081fd5b81516111dd81611fe0565b600080600080600060a086880312156118b5578081fd5b85356118c081611fcb565b945060208601356118d081611fcb565b93506040860135925060608601356118e781611fcb565b915060808601356118f781611fcb565b809150509295509295909350565b60008060408385031215611917578182fd5b823561192281611fcb565b915060208381013567ffffffffffffffff81111561193e578283fd5b80850186601f82011261194f578384fd5b8035915061195f61182a83611fab565b82815283810190828501858502840186018a101561197b578687fd5b8693505b848410156119a657803561199281611fcb565b83526001939093019291850191850161197f565b5080955050505050509250929050565b600080604083850312156119c8578182fd5b82356119d381611fcb565b915060208301356119e381611fcb565b809150509250929050565b60008060408385031215611a00578182fd5b8235611a0b81611fcb565b946020939093013593505050565b60008060008060808587031215611a2e578384fd5b8435611a3981611fcb565b9350602085013592506040850135611a5081611fcb565b91506060850135611a6081611fcb565b939692955090935050565b60008060008060808587031215611a80578182fd5b8435611a8b81611fcb565b9350602085013592506040850135611aa281611fcb565b91506060850135611a6081611fe0565b600060208284031215611ac3578081fd5b8151600381106111dd578182fd5b600060208284031215611ae2578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b81811015611b575783516001600160a01b031683529284019291840191600101611b32565b50909695505050505050565b901515815260200190565b6000602080835283518082850152825b81811015611b9a57858101830151858201604001528201611b7e565b81811115611bab5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526015908201527420b2323932b9b9903737ba1034b71030b93930bc9760591b604082015260600190565b60208082526028908201527f4d75737420626520612076616c696420616e6420696e697469616c697a65642060408201526729b2ba2a37b5b2b760c11b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601e908201527f4d7573742062652070656e64696e6720696e697469616c697a6174696f6e0000604082015260600190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b60208082526018908201527f4f6e6c7920746865206d6f64756c652063616e2063616c6c0000000000000000604082015260600190565b60208082526018908201527f49737375616e6365206e6f7420696e697469616c697a65640000000000000000604082015260600190565b60208082526022908201527f5265626173696e6720636f6d706f6e656e7420616c726561647920656e61626c604082015261195960f21b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b60208082526024908201527f4d6f64756c65206d75737420626520656e61626c6564206f6e20636f6e74726f604082015263363632b960e11b606082015260800190565b60208082526023908201527f4d75737420626520636f6e74726f6c6c65722d656e61626c656420536574546f60408201526235b2b760e91b606082015260800190565b6020808252601c908201527f4d7573742062652074686520536574546f6b656e206d616e6167657200000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601e908201527f5265626173696e6720636f6d706f6e656e74206e6f7420656e61626c65640000604082015260600190565b60405181810167ffffffffffffffff81118282101715611fa357600080fd5b604052919050565b600067ffffffffffffffff821115611fc1578081fd5b5060209081020190565b6001600160a01b0381168114610e0257600080fd5b8015158114610e0257600080fdfea2646970667358221220df924066d527d897128b3ab46a512df66aa488cf4184e9a6c6009427fe4492bd64736f6c634300060a0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101165760003560e01c8063946d9204116100a2578063c153dd0711610071578063c153dd071461016c578063d002630114610203578063f2fde38b14610223578063f77c479114610236578063fb42e7ec1461023e57610116565b8063946d9204146101ca5780639b19c2bf146101dd578063a5841194146101f0578063c137f4d71461011b57610116565b80635b136512116100e95780635b1365121461017f57806366c8d1f814610192578063715018a6146101a5578063847ef08d146101ad5780638da5cb5b146101b557610116565b80630fb96b211461011b5780632d49104a1461013057806335c2b333146101595780633fe6106b1461016c575b600080fd5b61012e610129366004611a6b565b610251565b005b61014361013e3660046117a9565b610262565b6040516101509190611b16565b60405180910390f35b61012e610167366004611905565b6102d8565b61012e61017a3660046119ee565b6102f1565b61012e61018d3660046119b6565b610304565b61012e6101a0366004611905565b610412565b61012e610526565b61012e6105a5565b6101bd6107a0565b6040516101509190611ae9565b61012e6101d8366004611905565b6107b0565b61012e6101eb366004611a19565b610924565b61012e6101fe3660046117a9565b610933565b6102166102113660046119b6565b610bc7565b6040516101509190611b63565b61012e6102313660046117a9565b610be7565b6101bd610c9e565b61012e61024c36600461189e565b610cad565b8361025b81610cc0565b5050505050565b6001600160a01b0381166000908152600460209081526040918290208054835181840281018401909452808452606093928301828280156102cc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102ae575b50505050509050919050565b816102e281610e05565b6102ec8383610e50565b505050565b816102fb81610cc0565b6102ec83610933565b8161030e81610e05565b6040516335fc6c9f60e21b81526001600160a01b0384169063d7f1b27c9061033a908590600401611ae9565b60206040518083038186803b15801561035257600080fd5b505afa158015610366573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038a9190611882565b6103af5760405162461bcd60e51b81526004016103a690611d21565b60405180910390fd5b6040516306cd8db760e51b81526001600160a01b0383169063d9b1b6e0906103db908690600401611ae9565b600060405180830381600087803b1580156103f557600080fd5b505af1158015610409573d6000803e3d6000fd5b50505050505050565b8161041c81610e05565b60005b82518110156104db57600083828151811061043657fe5b6020908102919091018101516001600160a01b0380881660009081526003845260408082209284168252919093529091205490915060ff1661048a5760405162461bcd60e51b81526004016103a690611f4d565b6001600160a01b0380861660008181526003602090815260408083209486168352938152838220805460ff191690559181526004909152206104d2908263ffffffff610f7216565b5060010161041f565b5060001515836001600160a01b03167f4350523f9d22b1cba0809180a64bb309a4840366d65bcea72c1316cfa80528ac846040516105199190611b16565b60405180910390a3505050565b61052e61109e565b6002546001600160a01b0390811691161461055b5760405162461bcd60e51b81526004016103a690611ddb565b6002546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600280546001600160a01b0319169055565b336105af81610e2b565b336105b981610933565b6001600160a01b03811660009081526004602090815260409182902080548351818402810184019094528084526060939283018282801561062357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610605575b50939450600093505050505b815181101561068657600082828151811061064657fe5b6020908102919091018101516001600160a01b03808716600090815260038452604080822092909316815292529020805460ff191690555060010161062f565b506001600160a01b03821660009081526004602052604081206106a891611776565b6060826001600160a01b031663b2494df36040518163ffffffff1660e01b815260040160006040518083038186803b1580156106e357600080fd5b505afa1580156106f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261071f91908101906117e1565b905060005b815181101561025b5781818151811061073957fe5b60200260200101516001600160a01b031663e0799620856040518263ffffffff1660e01b815260040161076c9190611ae9565b600060405180830381600087803b15801561078657600080fd5b505af1925050508015610797575060015b50600101610724565b6002546001600160a01b03165b90565b81336107bc82826110a2565b836107c6816110cc565b846001600160a01b0316630ffe0f1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561080157600080fd5b505af1158015610815573d6000803e3d6000fd5b505050506060856001600160a01b031663b2494df36040518163ffffffff1660e01b815260040160006040518083038186803b15801561085457600080fd5b505afa158015610868573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261089091908101906117e1565b905060005b8151811015610911578181815181106108aa57fe5b60200260200101516001600160a01b031663d9b1b6e0886040518263ffffffff1660e01b81526004016108dd9190611ae9565b600060405180830381600087803b1580156108f757600080fd5b505af1925050508015610908575060015b50600101610895565b5061091c8686610e50565b505050505050565b8361092e81610cc0565b61025b855b600260015414156109565760405162461bcd60e51b81526004016103a690611f16565b60026001558061096581610e2b565b6000826001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109a057600080fd5b505afa1580156109b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d89190611ad1565b90508015610bbe576001600160a01b038316600090815260046020908152604091829020805483518184028101840190945280845260609392830182828015610a4a57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a2c575b50939450600093505050505b8151811015610bbb576000828281518110610a6d57fe5b602002602001015190506000610afd876001600160a01b03166366cb8d2f846040518263ffffffff1660e01b8152600401610aa89190611ae9565b60206040518083038186803b158015610ac057600080fd5b505afa158015610ad4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af89190611ad1565b61118d565b90506000610b8d86846001600160a01b03166370a082318b6040518263ffffffff1660e01b8152600401610b319190611ae9565b60206040518083038186803b158015610b4957600080fd5b505afa158015610b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b819190611ad1565b9063ffffffff6111b316565b9050808214610bb057610bb06001600160a01b038916848363ffffffff6111e616565b505050600101610a56565b50505b50506001805550565b600360209081526000928352604080842090915290825290205460ff1681565b610bef61109e565b6002546001600160a01b03908116911614610c1c5760405162461bcd60e51b81526004016103a690611ddb565b6001600160a01b038116610c425760405162461bcd60e51b81526004016103a690611c38565b6002546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031681565b84610cb781610cc0565b61091c86610933565b6002604051631ade272960e11b81526001600160a01b038316906335bc4e5290610cee903390600401611ae9565b60206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190611ab2565b6002811115610d4957fe5b14610d665760405162461bcd60e51b81526004016103a690611cea565b6000546040516342f6e38960e01b81526001600160a01b03909116906342f6e38990610d96903390600401611ae9565b60206040518083038186803b158015610dae57600080fd5b505afa158015610dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de69190611882565b610e025760405162461bcd60e51b81526004016103a690611e58565b50565b610e0f8133611364565b610e2b5760405162461bcd60e51b81526004016103a690611edf565b610e34816113f2565b610e025760405162461bcd60e51b81526004016103a690611bf0565b60005b8151811015610f28576000828281518110610e6a57fe5b6020908102919091018101516001600160a01b0380871660009081526003845260408082209284168252919093529091205490915060ff1615610ebf5760405162461bcd60e51b81526004016103a690611d58565b6001600160a01b03808516600081815260036020908152604080832095909416808352948152838220805460ff19166001908117909155928252600481529281208054808401825590825292902090910180546001600160a01b03191690921790915501610e53565b5060011515826001600160a01b03167f4350523f9d22b1cba0809180a64bb309a4840366d65bcea72c1316cfa80528ac83604051610f669190611b16565b60405180910390a35050565b600080610fd884805480602002602001604051908101604052809291908181526020018280548015610fcd57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610faf575b5050505050846114f6565b9150915080610ff95760405162461bcd60e51b81526004016103a690611bc1565b83546000190182811461106b5784818154811061101257fe5b9060005260206000200160009054906101000a90046001600160a01b031685848154811061103c57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b8480548061107557fe5b600082815260209020810160001990810180546001600160a01b03191690550190555050505050565b3390565b6110ac8282611364565b6110c85760405162461bcd60e51b81526004016103a690611edf565b5050565b600054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec906110fc908490600401611ae9565b60206040518083038186803b15801561111457600080fd5b505afa158015611128573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114c9190611882565b6111685760405162461bcd60e51b81526004016103a690611e9c565b6111718161155c565b610e025760405162461bcd60e51b81526004016103a690611c7e565b6000808212156111af5760405162461bcd60e51b81526004016103a690611cb5565b5090565b60006111dd826111d185670de0b6b3a764000063ffffffff61158b16565b9063ffffffff6115c516565b90505b92915050565b60006111f28484611607565b9050801580156112025750600082115b1561127957611211848461168e565b611274576040516304e3532760e41b81526001600160a01b03851690634e35327090611241908690600401611ae9565b600060405180830381600087803b15801561125b57600080fd5b505af115801561126f573d6000803e3d6000fd5b505050505b6112f6565b808015611284575081155b156112f657611293848461168e565b6112f657604051636f86c89760e01b81526001600160a01b03851690636f86c897906112c3908690600401611ae9565b600060405180830381600087803b1580156112dd57600080fd5b505af11580156112f1573d6000803e3d6000fd5b505050505b836001600160a01b0316632ba57d178461130f8561171a565b6040518363ffffffff1660e01b815260040161132c929190611afd565b600060405180830381600087803b15801561134657600080fd5b505af115801561135a573d6000803e3d6000fd5b5050505050505050565b6000816001600160a01b0316836001600160a01b031663481c6a756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113a957600080fd5b505afa1580156113bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e191906117c5565b6001600160a01b0316149392505050565b60008054604051631d3af8fb60e21b81526001600160a01b03909116906374ebe3ec90611423908590600401611ae9565b60206040518083038186803b15801561143b57600080fd5b505afa15801561144f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114739190611882565b80156111e057506040516335fc6c9f60e21b81526001600160a01b0383169063d7f1b27c906114a6903090600401611ae9565b60206040518083038186803b1580156114be57600080fd5b505afa1580156114d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e09190611882565b81516000908190815b8181101561154957846001600160a01b031686828151811061151d57fe5b60200260200101516001600160a01b03161415611541579250600191506115559050565b6001016114ff565b50600019600092509250505b9250929050565b6040516353bae5f760e01b81526000906001600160a01b038316906353bae5f7906114a6903090600401611ae9565b60008261159a575060006111e0565b828202828482816115a757fe5b04146111dd5760405162461bcd60e51b81526004016103a690611d9a565b60006111dd83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061173f565b600080836001600160a01b03166366cb8d2f846040518263ffffffff1660e01b81526004016116369190611ae9565b60206040518083038186803b15801561164e57600080fd5b505afa158015611662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116869190611ad1565b139392505050565b600080836001600160a01b031663a7bdad03846040518263ffffffff1660e01b81526004016116bd9190611ae9565b60006040518083038186803b1580156116d557600080fd5b505afa1580156116e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261171191908101906117e1565b51119392505050565b6000600160ff1b82106111af5760405162461bcd60e51b81526004016103a690611e10565b600081836117605760405162461bcd60e51b81526004016103a69190611b6e565b50600083858161176c57fe5b0495945050505050565b5080546000825590600052602060002090810190610e0291906107ad91905b808211156111af5760008155600101611795565b6000602082840312156117ba578081fd5b81356111dd81611fcb565b6000602082840312156117d6578081fd5b81516111dd81611fcb565b600060208083850312156117f3578182fd5b825167ffffffffffffffff811115611809578283fd5b80840185601f82011261181a578384fd5b8051915061182f61182a83611fab565b611f84565b828152838101908285018585028401860189101561184b578687fd5b8693505b8484101561187657805161186281611fcb565b83526001939093019291850191850161184f565b50979650505050505050565b600060208284031215611893578081fd5b81516111dd81611fe0565b600080600080600060a086880312156118b5578081fd5b85356118c081611fcb565b945060208601356118d081611fcb565b93506040860135925060608601356118e781611fcb565b915060808601356118f781611fcb565b809150509295509295909350565b60008060408385031215611917578182fd5b823561192281611fcb565b915060208381013567ffffffffffffffff81111561193e578283fd5b80850186601f82011261194f578384fd5b8035915061195f61182a83611fab565b82815283810190828501858502840186018a101561197b578687fd5b8693505b848410156119a657803561199281611fcb565b83526001939093019291850191850161197f565b5080955050505050509250929050565b600080604083850312156119c8578182fd5b82356119d381611fcb565b915060208301356119e381611fcb565b809150509250929050565b60008060408385031215611a00578182fd5b8235611a0b81611fcb565b946020939093013593505050565b60008060008060808587031215611a2e578384fd5b8435611a3981611fcb565b9350602085013592506040850135611a5081611fcb565b91506060850135611a6081611fcb565b939692955090935050565b60008060008060808587031215611a80578182fd5b8435611a8b81611fcb565b9350602085013592506040850135611aa281611fcb565b91506060850135611a6081611fe0565b600060208284031215611ac3578081fd5b8151600381106111dd578182fd5b600060208284031215611ae2578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b81811015611b575783516001600160a01b031683529284019291840191600101611b32565b50909695505050505050565b901515815260200190565b6000602080835283518082850152825b81811015611b9a57858101830151858201604001528201611b7e565b81811115611bab5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526015908201527420b2323932b9b9903737ba1034b71030b93930bc9760591b604082015260600190565b60208082526028908201527f4d75737420626520612076616c696420616e6420696e697469616c697a65642060408201526729b2ba2a37b5b2b760c11b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601e908201527f4d7573742062652070656e64696e6720696e697469616c697a6174696f6e0000604082015260600190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b60208082526018908201527f4f6e6c7920746865206d6f64756c652063616e2063616c6c0000000000000000604082015260600190565b60208082526018908201527f49737375616e6365206e6f7420696e697469616c697a65640000000000000000604082015260600190565b60208082526022908201527f5265626173696e6720636f6d706f6e656e7420616c726561647920656e61626c604082015261195960f21b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b60208082526024908201527f4d6f64756c65206d75737420626520656e61626c6564206f6e20636f6e74726f604082015263363632b960e11b606082015260800190565b60208082526023908201527f4d75737420626520636f6e74726f6c6c65722d656e61626c656420536574546f60408201526235b2b760e91b606082015260800190565b6020808252601c908201527f4d7573742062652074686520536574546f6b656e206d616e6167657200000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601e908201527f5265626173696e6720636f6d706f6e656e74206e6f7420656e61626c65640000604082015260600190565b60405181810167ffffffffffffffff81118282101715611fa357600080fd5b604052919050565b600067ffffffffffffffff821115611fc1578081fd5b5060209081020190565b6001600160a01b0381168114610e0257600080fd5b8015158114610e0257600080fdfea2646970667358221220df924066d527d897128b3ab46a512df66aa488cf4184e9a6c6009427fe4492bd64736f6c634300060a0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/set/SetValuer.json b/external/abi/set/SetValuer.json new file mode 100644 index 000000000..6ec9a3b7f --- /dev/null +++ b/external/abi/set/SetValuer.json @@ -0,0 +1,91 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SetValuer", + "sourceName": "contracts/protocol/SetValuer.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IController", + "name": "_controller", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_component", + "type": "address" + }, + { + "internalType": "address", + "name": "_quoteAsset", + "type": "address" + } + ], + "name": "calculateComponentValuation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [ + { + "internalType": "contract ISetToken", + "name": "_setToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_quoteAsset", + "type": "address" + } + ], + "name": "calculateSetTokenValuation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "gas": "0xa7d8c0" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610ef5380380610ef583398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610082565b600060208284031215610065578081fd5b81516001600160a01b038116811461007b578182fd5b9392505050565b610e64806100916000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80636101c54014610046578063c8a389841461006f578063f77c479114610082575b600080fd5b610059610054366004610b4b565b610097565b6040516100669190610de6565b60405180910390f35b61005961007d366004610b83565b61046d565b61008a61081b565b6040516100669190610c06565b6000805481906100af906001600160a01b031661082a565b90506000816001600160a01b031663342833546040518163ffffffff1660e01b815260040160206040518083038186803b1580156100ec57600080fd5b505afa158015610100573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101249190610a64565b90506060856001600160a01b03166399d50d5d6040518163ffffffff1660e01b815260040160006040518083038186803b15801561016157600080fd5b505afa158015610175573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261019d9190810190610a80565b90506000805b825181101561039d5760008382815181106101ba57fe5b602002602001015190506000866001600160a01b031663ac41865a83886040518363ffffffff1660e01b81526004016101f4929190610c1a565b60206040518083038186803b15801561020c57600080fd5b505afa158015610220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102449190610bcd565b905060008a6001600160a01b031663eaf993e1846040518263ffffffff1660e01b81526004016102749190610c06565b60206040518083038186803b15801561028c57600080fd5b505afa1580156102a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c49190610bcd565b90506000836001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561030157600080fd5b505afa158015610315573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103399190610be5565b60ff169050600a81900a600061035e610351836108aa565b859063ffffffff6108d316565b90506103898861037d610370886108aa565b849063ffffffff61090416565b9063ffffffff61092216565b975050600190950194506101a39350505050565b50856001600160a01b0316836001600160a01b03161461045757604051635620c32d60e11b81526000906001600160a01b0386169063ac41865a906103e8908a908890600401610c1a565b60206040518083038186803b15801561040057600080fd5b505afa158015610414573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104389190610bcd565b9050610453610446826108aa565b839063ffffffff6108d316565b9150505b61046081610968565b9450505050505b92915050565b60405163df5e9b2960e01b81526000906001600160a01b0385169063df5e9b299061049c908690600401610c06565b60206040518083038186803b1580156104b457600080fd5b505afa1580156104c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ec9190610b2b565b6105115760405162461bcd60e51b815260040161050890610daf565b60405180910390fd5b60008054610527906001600160a01b031661082a565b90506000816001600160a01b031663342833546040518163ffffffff1660e01b815260040160206040518083038186803b15801561056457600080fd5b505afa158015610578573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059c9190610a64565b9050600080836001600160a01b031663ac41865a88856040518363ffffffff1660e01b81526004016105cf929190610c1a565b60206040518083038186803b1580156105e757600080fd5b505afa1580156105fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061f9190610bcd565b90506000886001600160a01b031663eaf993e1896040518263ffffffff1660e01b815260040161064f9190610c06565b60206040518083038186803b15801561066757600080fd5b505afa15801561067b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069f9190610bcd565b90506000886001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156106dc57600080fd5b505afa1580156106f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107149190610be5565b60ff169050600a81900a600061072c610351836108aa565b905061074761073a866108aa565b829063ffffffff61090416565b9550896001600160a01b0316876001600160a01b03161461080257604051635620c32d60e11b81526000906001600160a01b038a169063ac41865a90610793908e908c90600401610c1a565b60206040518083038186803b1580156107ab57600080fd5b505afa1580156107bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e39190610bcd565b90506107fe6107f1826108aa565b889063ffffffff6108d316565b9650505b61080b86610968565b9c9b505050505050505050505050565b6000546001600160a01b031681565b6040516373b2e76b60e11b81526000906001600160a01b0383169063e765ced69061085a90600190600401610de6565b60206040518083038186803b15801561087257600080fd5b505afa158015610886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104679190610a64565b6000600160ff1b82106108cf5760405162461bcd60e51b815260040161050890610d32565b5090565b60006108fd826108f185670de0b6b3a764000063ffffffff61098a16565b9063ffffffff6109f516565b9392505050565b60006108fd670de0b6b3a76400006108f1858563ffffffff61098a16565b60008282018183128015906109375750838112155b8061094c575060008312801561094c57508381125b6108fd5760405162461bcd60e51b815260040161050890610c34565b6000808212156108cf5760405162461bcd60e51b815260040161050890610c75565b60008261099957506000610467565b826000191480156109ad5750600160ff1b82145b156109ca5760405162461bcd60e51b815260040161050890610ceb565b828202828482816109d757fe5b05146108fd5760405162461bcd60e51b815260040161050890610ceb565b600081610a145760405162461bcd60e51b815260040161050890610d7a565b81600019148015610a285750600160ff1b83145b15610a455760405162461bcd60e51b815260040161050890610caa565b6000828481610a5057fe5b05949350505050565b805161046781610e16565b600060208284031215610a75578081fd5b81516108fd81610e16565b60006020808385031215610a92578182fd5b825167ffffffffffffffff80821115610aa9578384fd5b81850186601f820112610aba578485fd5b8051925081831115610aca578485fd5b8383029150610ada848301610def565b8381528481019082860184840187018a1015610af4578788fd5b8794505b85851015610b1e57610b0a8a82610a59565b835260019490940193918601918601610af8565b5098975050505050505050565b600060208284031215610b3c578081fd5b815180151581146108fd578182fd5b60008060408385031215610b5d578081fd5b8235610b6881610e16565b91506020830135610b7881610e16565b809150509250929050565b600080600060608486031215610b97578081fd5b8335610ba281610e16565b92506020840135610bb281610e16565b91506040840135610bc281610e16565b809150509250925092565b600060208284031215610bde578081fd5b5051919050565b600060208284031215610bf6578081fd5b815160ff811681146108fd578182fd5b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b60208082526019908201527f436f6d706f6e656e74206e6f7420696e20536574546f6b656e00000000000000604082015260600190565b90815260200190565b60405181810167ffffffffffffffff81118282101715610e0e57600080fd5b604052919050565b6001600160a01b0381168114610e2b57600080fd5b5056fea264697066735822122065ff5e8ecddcbf4aa684288461b56febd2669852205db5864eab9506f49ed77b64736f6c634300060a0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80636101c54014610046578063c8a389841461006f578063f77c479114610082575b600080fd5b610059610054366004610b4b565b610097565b6040516100669190610de6565b60405180910390f35b61005961007d366004610b83565b61046d565b61008a61081b565b6040516100669190610c06565b6000805481906100af906001600160a01b031661082a565b90506000816001600160a01b031663342833546040518163ffffffff1660e01b815260040160206040518083038186803b1580156100ec57600080fd5b505afa158015610100573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101249190610a64565b90506060856001600160a01b03166399d50d5d6040518163ffffffff1660e01b815260040160006040518083038186803b15801561016157600080fd5b505afa158015610175573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261019d9190810190610a80565b90506000805b825181101561039d5760008382815181106101ba57fe5b602002602001015190506000866001600160a01b031663ac41865a83886040518363ffffffff1660e01b81526004016101f4929190610c1a565b60206040518083038186803b15801561020c57600080fd5b505afa158015610220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102449190610bcd565b905060008a6001600160a01b031663eaf993e1846040518263ffffffff1660e01b81526004016102749190610c06565b60206040518083038186803b15801561028c57600080fd5b505afa1580156102a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c49190610bcd565b90506000836001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561030157600080fd5b505afa158015610315573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103399190610be5565b60ff169050600a81900a600061035e610351836108aa565b859063ffffffff6108d316565b90506103898861037d610370886108aa565b849063ffffffff61090416565b9063ffffffff61092216565b975050600190950194506101a39350505050565b50856001600160a01b0316836001600160a01b03161461045757604051635620c32d60e11b81526000906001600160a01b0386169063ac41865a906103e8908a908890600401610c1a565b60206040518083038186803b15801561040057600080fd5b505afa158015610414573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104389190610bcd565b9050610453610446826108aa565b839063ffffffff6108d316565b9150505b61046081610968565b9450505050505b92915050565b60405163df5e9b2960e01b81526000906001600160a01b0385169063df5e9b299061049c908690600401610c06565b60206040518083038186803b1580156104b457600080fd5b505afa1580156104c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ec9190610b2b565b6105115760405162461bcd60e51b815260040161050890610daf565b60405180910390fd5b60008054610527906001600160a01b031661082a565b90506000816001600160a01b031663342833546040518163ffffffff1660e01b815260040160206040518083038186803b15801561056457600080fd5b505afa158015610578573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059c9190610a64565b9050600080836001600160a01b031663ac41865a88856040518363ffffffff1660e01b81526004016105cf929190610c1a565b60206040518083038186803b1580156105e757600080fd5b505afa1580156105fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061f9190610bcd565b90506000886001600160a01b031663eaf993e1896040518263ffffffff1660e01b815260040161064f9190610c06565b60206040518083038186803b15801561066757600080fd5b505afa15801561067b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069f9190610bcd565b90506000886001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156106dc57600080fd5b505afa1580156106f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107149190610be5565b60ff169050600a81900a600061072c610351836108aa565b905061074761073a866108aa565b829063ffffffff61090416565b9550896001600160a01b0316876001600160a01b03161461080257604051635620c32d60e11b81526000906001600160a01b038a169063ac41865a90610793908e908c90600401610c1a565b60206040518083038186803b1580156107ab57600080fd5b505afa1580156107bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e39190610bcd565b90506107fe6107f1826108aa565b889063ffffffff6108d316565b9650505b61080b86610968565b9c9b505050505050505050505050565b6000546001600160a01b031681565b6040516373b2e76b60e11b81526000906001600160a01b0383169063e765ced69061085a90600190600401610de6565b60206040518083038186803b15801561087257600080fd5b505afa158015610886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104679190610a64565b6000600160ff1b82106108cf5760405162461bcd60e51b815260040161050890610d32565b5090565b60006108fd826108f185670de0b6b3a764000063ffffffff61098a16565b9063ffffffff6109f516565b9392505050565b60006108fd670de0b6b3a76400006108f1858563ffffffff61098a16565b60008282018183128015906109375750838112155b8061094c575060008312801561094c57508381125b6108fd5760405162461bcd60e51b815260040161050890610c34565b6000808212156108cf5760405162461bcd60e51b815260040161050890610c75565b60008261099957506000610467565b826000191480156109ad5750600160ff1b82145b156109ca5760405162461bcd60e51b815260040161050890610ceb565b828202828482816109d757fe5b05146108fd5760405162461bcd60e51b815260040161050890610ceb565b600081610a145760405162461bcd60e51b815260040161050890610d7a565b81600019148015610a285750600160ff1b83145b15610a455760405162461bcd60e51b815260040161050890610caa565b6000828481610a5057fe5b05949350505050565b805161046781610e16565b600060208284031215610a75578081fd5b81516108fd81610e16565b60006020808385031215610a92578182fd5b825167ffffffffffffffff80821115610aa9578384fd5b81850186601f820112610aba578485fd5b8051925081831115610aca578485fd5b8383029150610ada848301610def565b8381528481019082860184840187018a1015610af4578788fd5b8794505b85851015610b1e57610b0a8a82610a59565b835260019490940193918601918601610af8565b5098975050505050505050565b600060208284031215610b3c578081fd5b815180151581146108fd578182fd5b60008060408385031215610b5d578081fd5b8235610b6881610e16565b91506020830135610b7881610e16565b809150509250929050565b600080600060608486031215610b97578081fd5b8335610ba281610e16565b92506020840135610bb281610e16565b91506040840135610bc281610e16565b809150509250925092565b600060208284031215610bde578081fd5b5051919050565b600060208284031215610bf6578081fd5b815160ff811681146108fd578182fd5b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b60208082526019908201527f436f6d706f6e656e74206e6f7420696e20536574546f6b656e00000000000000604082015260600190565b90815260200190565b60405181810167ffffffffffffffff81118282101715610e0e57600080fd5b604052919050565b6001600160a01b0381168114610e2b57600080fd5b5056fea264697066735822122065ff5e8ecddcbf4aa684288461b56febd2669852205db5864eab9506f49ed77b64736f6c634300060a0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/contracts/set/CustomOracleNAVIssuanceModule.sol b/external/contracts/set/CustomOracleNAVIssuanceModule.sol new file mode 100644 index 000000000..0d202b333 --- /dev/null +++ b/external/contracts/set/CustomOracleNAVIssuanceModule.sol @@ -0,0 +1,1125 @@ +/* + Copyright 2020 Set Labs Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache License, Version 2.0 +*/ + +pragma solidity 0.6.10; +pragma experimental "ABIEncoderV2"; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; +import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol"; + +import { AddressArrayUtils } from "../../../lib/AddressArrayUtils.sol"; +import { IController } from "../../../interfaces/IController.sol"; +import { ISetValuer } from "../../../interfaces/ISetValuer.sol"; +import { INAVIssuanceHook } from "../../../interfaces/INAVIssuanceHook.sol"; +import { Invoke } from "../../lib/Invoke.sol"; +import { ISetToken } from "../../../interfaces/ISetToken.sol"; +import { IWETH } from "../../../interfaces/external/IWETH.sol"; +import { ModuleBase } from "../../lib/ModuleBase.sol"; +import { Position } from "../../lib/Position.sol"; +import { PreciseUnitMath } from "../../../lib/PreciseUnitMath.sol"; +import { ResourceIdentifier } from "../../lib/ResourceIdentifier.sol"; + +/** + * @title CustomOracleNavIssuanceModule + * @author Set Protocol + * + * Module that enables issuance and redemption with any valid ERC20 token or ETH if allowed by the manager. Sender receives + * a proportional amount of SetTokens on issuance or ERC20 token on redemption based on the calculated net asset value using + * oracle prices. Manager is able to enforce a premium / discount on issuance / redemption to avoid arbitrage and front + * running when relying on oracle prices. Managers can charge a fee (denominated in reserve asset). + */ +contract CustomOracleNavIssuanceModule is ModuleBase, ReentrancyGuard { + using AddressArrayUtils for address[]; + using Invoke for ISetToken; + using Position for ISetToken; + using PreciseUnitMath for uint256; + using PreciseUnitMath for int256; + using ResourceIdentifier for IController; + using SafeMath for uint256; + using SafeCast for int256; + using SafeCast for uint256; + using SignedSafeMath for int256; + + /* ============ Events ============ */ + + event SetTokenNAVIssued( + ISetToken indexed _setToken, + address _issuer, + address _to, + address _reserveAsset, + address _hookContract, + uint256 _setTokenQuantity, + uint256 _managerFee, + uint256 _premium + ); + + event SetTokenNAVRedeemed( + ISetToken indexed _setToken, + address _redeemer, + address _to, + address _reserveAsset, + address _hookContract, + uint256 _setTokenQuantity, + uint256 _managerFee, + uint256 _premium + ); + + event ReserveAssetAdded( + ISetToken indexed _setToken, + address _newReserveAsset + ); + + event ReserveAssetRemoved( + ISetToken indexed _setToken, + address _removedReserveAsset + ); + + event PremiumEdited( + ISetToken indexed _setToken, + uint256 _newPremium + ); + + event ManagerFeeEdited( + ISetToken indexed _setToken, + uint256 _newManagerFee, + uint256 _index + ); + + event FeeRecipientEdited( + ISetToken indexed _setToken, + address _feeRecipient + ); + + /* ============ Structs ============ */ + + struct NAVIssuanceSettings { + INAVIssuanceHook managerIssuanceHook; // Issuance hook configurations + INAVIssuanceHook managerRedemptionHook; // Redemption hook configurations + ISetValuer setValuer; // Optional custom set valuer. If address(0) is provided, fetch the default one from the controller + address[] reserveAssets; // Allowed reserve assets - Must have a price enabled with the price oracle + address feeRecipient; // Manager fee recipient + uint256[2] managerFees; // Manager fees. 0 index is issue and 1 index is redeem fee (0.01% = 1e14, 1% = 1e16) + uint256 maxManagerFee; // Maximum fee manager is allowed to set for issue and redeem + uint256 premiumPercentage; // Premium percentage (0.01% = 1e14, 1% = 1e16). This premium is a buffer around oracle + // prices paid by user to the SetToken, which prevents arbitrage and oracle front running + uint256 maxPremiumPercentage; // Maximum premium percentage manager is allowed to set (configured by manager) + uint256 minSetTokenSupply; // Minimum SetToken supply required for issuance and redemption + // to prevent dramatic inflationary changes to the SetToken's position multiplier + } + + struct ActionInfo { + uint256 preFeeReserveQuantity; // Reserve value before fees; During issuance, represents raw quantity + // During redeem, represents post-premium value + uint256 protocolFees; // Total protocol fees (direct + manager revenue share) + uint256 managerFee; // Total manager fee paid in reserve asset + uint256 netFlowQuantity; // When issuing, quantity of reserve asset sent to SetToken + // When redeeming, quantity of reserve asset sent to redeemer + uint256 setTokenQuantity; // When issuing, quantity of SetTokens minted to mintee + // When redeeming, quantity of SetToken redeemed + uint256 previousSetTokenSupply; // SetToken supply prior to issue/redeem action + uint256 newSetTokenSupply; // SetToken supply after issue/redeem action + int256 newPositionMultiplier; // SetToken position multiplier after issue/redeem + uint256 newReservePositionUnit; // SetToken reserve asset position unit after issue/redeem + } + + /* ============ State Variables ============ */ + + // Wrapped ETH address + IWETH public immutable weth; + + // Mapping of SetToken to NAV issuance settings struct + mapping(ISetToken => NAVIssuanceSettings) public navIssuanceSettings; + + // Mapping to efficiently check a SetToken's reserve asset validity + // SetToken => reserveAsset => isReserveAsset + mapping(ISetToken => mapping(address => bool)) public isReserveAsset; + + /* ============ Constants ============ */ + + // 0 index stores the manager fee in managerFees array, percentage charged on issue (denominated in reserve asset) + uint256 constant internal MANAGER_ISSUE_FEE_INDEX = 0; + + // 1 index stores the manager fee percentage in managerFees array, charged on redeem + uint256 constant internal MANAGER_REDEEM_FEE_INDEX = 1; + + // 0 index stores the manager revenue share protocol fee % on the controller, charged in the issuance function + uint256 constant internal PROTOCOL_ISSUE_MANAGER_REVENUE_SHARE_FEE_INDEX = 0; + + // 1 index stores the manager revenue share protocol fee % on the controller, charged in the redeem function + uint256 constant internal PROTOCOL_REDEEM_MANAGER_REVENUE_SHARE_FEE_INDEX = 1; + + // 2 index stores the direct protocol fee % on the controller, charged in the issuance function + uint256 constant internal PROTOCOL_ISSUE_DIRECT_FEE_INDEX = 2; + + // 3 index stores the direct protocol fee % on the controller, charged in the redeem function + uint256 constant internal PROTOCOL_REDEEM_DIRECT_FEE_INDEX = 3; + + /* ============ Constructor ============ */ + + /** + * @param _controller Address of controller contract + * @param _weth Address of wrapped eth + */ + constructor(IController _controller, IWETH _weth) public ModuleBase(_controller) { + weth = _weth; + } + + /* ============ External Functions ============ */ + + /** + * Deposits the allowed reserve asset into the SetToken and mints the appropriate % of Net Asset Value of the SetToken + * to the specified _to address. + * + * @param _setToken Instance of the SetToken contract + * @param _reserveAsset Address of the reserve asset to issue with + * @param _reserveAssetQuantity Quantity of the reserve asset to issue with + * @param _minSetTokenReceiveQuantity Min quantity of SetToken to receive after issuance + * @param _to Address to mint SetToken to + */ + function issue( + ISetToken _setToken, + address _reserveAsset, + uint256 _reserveAssetQuantity, + uint256 _minSetTokenReceiveQuantity, + address _to + ) + external + nonReentrant + onlyValidAndInitializedSet(_setToken) + { + _validateCommon(_setToken, _reserveAsset, _reserveAssetQuantity); + + _callPreIssueHooks(_setToken, _reserveAsset, _reserveAssetQuantity, msg.sender, _to); + + ActionInfo memory issueInfo = _createIssuanceInfo(_setToken, _reserveAsset, _reserveAssetQuantity); + + _validateIssuanceInfo(_setToken, _minSetTokenReceiveQuantity, issueInfo); + + _transferCollateralAndHandleFees(_setToken, IERC20(_reserveAsset), issueInfo); + + _handleIssueStateUpdates(_setToken, _reserveAsset, _to, issueInfo); + } + + /** + * Wraps ETH and deposits WETH if allowed into the SetToken and mints the appropriate % of Net Asset Value of the SetToken + * to the specified _to address. + * + * @param _setToken Instance of the SetToken contract + * @param _minSetTokenReceiveQuantity Min quantity of SetToken to receive after issuance + * @param _to Address to mint SetToken to + */ + function issueWithEther( + ISetToken _setToken, + uint256 _minSetTokenReceiveQuantity, + address _to + ) + external + payable + nonReentrant + onlyValidAndInitializedSet(_setToken) + { + weth.deposit{ value: msg.value }(); + + _validateCommon(_setToken, address(weth), msg.value); + + _callPreIssueHooks(_setToken, address(weth), msg.value, msg.sender, _to); + + ActionInfo memory issueInfo = _createIssuanceInfo(_setToken, address(weth), msg.value); + + _validateIssuanceInfo(_setToken, _minSetTokenReceiveQuantity, issueInfo); + + _transferWETHAndHandleFees(_setToken, issueInfo); + + _handleIssueStateUpdates(_setToken, address(weth), _to, issueInfo); + } + + /** + * Redeems a SetToken into a valid reserve asset representing the appropriate % of Net Asset Value of the SetToken + * to the specified _to address. Only valid if there are available reserve units on the SetToken. + * + * @param _setToken Instance of the SetToken contract + * @param _reserveAsset Address of the reserve asset to redeem with + * @param _setTokenQuantity Quantity of SetTokens to redeem + * @param _minReserveReceiveQuantity Min quantity of reserve asset to receive + * @param _to Address to redeem reserve asset to + */ + function redeem( + ISetToken _setToken, + address _reserveAsset, + uint256 _setTokenQuantity, + uint256 _minReserveReceiveQuantity, + address _to + ) + external + nonReentrant + onlyValidAndInitializedSet(_setToken) + { + _validateCommon(_setToken, _reserveAsset, _setTokenQuantity); + + _callPreRedeemHooks(_setToken, _setTokenQuantity, msg.sender, _to); + + ActionInfo memory redeemInfo = _createRedemptionInfo(_setToken, _reserveAsset, _setTokenQuantity); + + _validateRedemptionInfo(_setToken, _minReserveReceiveQuantity, redeemInfo); + + _setToken.burn(msg.sender, _setTokenQuantity); + + // Instruct the SetToken to transfer the reserve asset back to the user + _setToken.strictInvokeTransfer( + _reserveAsset, + _to, + redeemInfo.netFlowQuantity + ); + + _handleRedemptionFees(_setToken, _reserveAsset, redeemInfo); + + _handleRedeemStateUpdates(_setToken, _reserveAsset, _to, redeemInfo); + } + + /** + * Redeems a SetToken into Ether (if WETH is valid) representing the appropriate % of Net Asset Value of the SetToken + * to the specified _to address. Only valid if there are available WETH units on the SetToken. + * + * @param _setToken Instance of the SetToken contract + * @param _setTokenQuantity Quantity of SetTokens to redeem + * @param _minReserveReceiveQuantity Min quantity of reserve asset to receive + * @param _to Address to redeem reserve asset to + */ + function redeemIntoEther( + ISetToken _setToken, + uint256 _setTokenQuantity, + uint256 _minReserveReceiveQuantity, + address payable _to + ) + external + nonReentrant + onlyValidAndInitializedSet(_setToken) + { + _validateCommon(_setToken, address(weth), _setTokenQuantity); + + _callPreRedeemHooks(_setToken, _setTokenQuantity, msg.sender, _to); + + ActionInfo memory redeemInfo = _createRedemptionInfo(_setToken, address(weth), _setTokenQuantity); + + _validateRedemptionInfo(_setToken, _minReserveReceiveQuantity, redeemInfo); + + _setToken.burn(msg.sender, _setTokenQuantity); + + // Instruct the SetToken to transfer WETH from SetToken to module + _setToken.strictInvokeTransfer( + address(weth), + address(this), + redeemInfo.netFlowQuantity + ); + + weth.withdraw(redeemInfo.netFlowQuantity); + + _to.transfer(redeemInfo.netFlowQuantity); + + _handleRedemptionFees(_setToken, address(weth), redeemInfo); + + _handleRedeemStateUpdates(_setToken, address(weth), _to, redeemInfo); + } + + /** + * SET MANAGER ONLY. Add an allowed reserve asset + * + * @param _setToken Instance of the SetToken + * @param _reserveAsset Address of the reserve asset to add + */ + function addReserveAsset(ISetToken _setToken, address _reserveAsset) external onlyManagerAndValidSet(_setToken) { + require(!isReserveAsset[_setToken][_reserveAsset], "Reserve asset already exists"); + + navIssuanceSettings[_setToken].reserveAssets.push(_reserveAsset); + isReserveAsset[_setToken][_reserveAsset] = true; + + emit ReserveAssetAdded(_setToken, _reserveAsset); + } + + /** + * SET MANAGER ONLY. Remove a reserve asset + * + * @param _setToken Instance of the SetToken + * @param _reserveAsset Address of the reserve asset to remove + */ + function removeReserveAsset(ISetToken _setToken, address _reserveAsset) external onlyManagerAndValidSet(_setToken) { + require(isReserveAsset[_setToken][_reserveAsset], "Reserve asset does not exist"); + + navIssuanceSettings[_setToken].reserveAssets = navIssuanceSettings[_setToken].reserveAssets.remove(_reserveAsset); + delete isReserveAsset[_setToken][_reserveAsset]; + + emit ReserveAssetRemoved(_setToken, _reserveAsset); + } + + /** + * SET MANAGER ONLY. Edit the premium percentage + * + * @param _setToken Instance of the SetToken + * @param _premiumPercentage Premium percentage in 10e16 (e.g. 10e16 = 1%) + */ + function editPremium(ISetToken _setToken, uint256 _premiumPercentage) external onlyManagerAndValidSet(_setToken) { + require(_premiumPercentage <= navIssuanceSettings[_setToken].maxPremiumPercentage, "Premium must be less than maximum allowed"); + + navIssuanceSettings[_setToken].premiumPercentage = _premiumPercentage; + + emit PremiumEdited(_setToken, _premiumPercentage); + } + + /** + * SET MANAGER ONLY. Edit manager fee + * + * @param _setToken Instance of the SetToken + * @param _managerFeePercentage Manager fee percentage in 10e16 (e.g. 10e16 = 1%) + * @param _managerFeeIndex Manager fee index. 0 index is issue fee, 1 index is redeem fee + */ + function editManagerFee( + ISetToken _setToken, + uint256 _managerFeePercentage, + uint256 _managerFeeIndex + ) + external + onlyManagerAndValidSet(_setToken) + { + require(_managerFeePercentage <= navIssuanceSettings[_setToken].maxManagerFee, "Manager fee must be less than maximum allowed"); + + navIssuanceSettings[_setToken].managerFees[_managerFeeIndex] = _managerFeePercentage; + + emit ManagerFeeEdited(_setToken, _managerFeePercentage, _managerFeeIndex); + } + + /** + * SET MANAGER ONLY. Edit the manager fee recipient + * + * @param _setToken Instance of the SetToken + * @param _managerFeeRecipient Manager fee recipient + */ + function editFeeRecipient(ISetToken _setToken, address _managerFeeRecipient) external onlyManagerAndValidSet(_setToken) { + require(_managerFeeRecipient != address(0), "Fee recipient must not be 0 address"); + + navIssuanceSettings[_setToken].feeRecipient = _managerFeeRecipient; + + emit FeeRecipientEdited(_setToken, _managerFeeRecipient); + } + + /** + * SET MANAGER ONLY. Initializes this module to the SetToken with hooks, allowed reserve assets, + * fees and issuance premium. Only callable by the SetToken's manager. Hook addresses are optional. + * Address(0) means that no hook will be called. + * + * @param _setToken Instance of the SetToken to issue + * @param _navIssuanceSettings NAVIssuanceSettings struct defining parameters + */ + function initialize( + ISetToken _setToken, + NAVIssuanceSettings memory _navIssuanceSettings + ) + external + onlySetManager(_setToken, msg.sender) + onlyValidAndPendingSet(_setToken) + { + require(_navIssuanceSettings.reserveAssets.length > 0, "Reserve assets must be greater than 0"); + require(_navIssuanceSettings.maxManagerFee < PreciseUnitMath.preciseUnit(), "Max manager fee must be less than 100%"); + require(_navIssuanceSettings.maxPremiumPercentage < PreciseUnitMath.preciseUnit(), "Max premium percentage must be less than 100%"); + require(_navIssuanceSettings.managerFees[0] <= _navIssuanceSettings.maxManagerFee, "Manager issue fee must be less than max"); + require(_navIssuanceSettings.managerFees[1] <= _navIssuanceSettings.maxManagerFee, "Manager redeem fee must be less than max"); + require(_navIssuanceSettings.premiumPercentage <= _navIssuanceSettings.maxPremiumPercentage, "Premium must be less than max"); + require(_navIssuanceSettings.feeRecipient != address(0), "Fee Recipient must be non-zero address."); + // Initial mint of Set cannot use NAVIssuance since minSetTokenSupply must be > 0 + require(_navIssuanceSettings.minSetTokenSupply > 0, "Min SetToken supply must be greater than 0"); + + for (uint256 i = 0; i < _navIssuanceSettings.reserveAssets.length; i++) { + require(!isReserveAsset[_setToken][_navIssuanceSettings.reserveAssets[i]], "Reserve assets must be unique"); + isReserveAsset[_setToken][_navIssuanceSettings.reserveAssets[i]] = true; + } + + navIssuanceSettings[_setToken] = _navIssuanceSettings; + + _setToken.initializeModule(); + } + + /** + * Removes this module from the SetToken, via call by the SetToken. Issuance settings and + * reserve asset states are deleted. + */ + function removeModule() external override { + ISetToken setToken = ISetToken(msg.sender); + for (uint256 i = 0; i < navIssuanceSettings[setToken].reserveAssets.length; i++) { + delete isReserveAsset[setToken][navIssuanceSettings[setToken].reserveAssets[i]]; + } + + delete navIssuanceSettings[setToken]; + } + + receive() external payable {} + + /* ============ External Getter Functions ============ */ + + function getReserveAssets(ISetToken _setToken) external view returns (address[] memory) { + return navIssuanceSettings[_setToken].reserveAssets; + } + + function getIssuePremium( + ISetToken _setToken, + address _reserveAsset, + uint256 _reserveAssetQuantity + ) + external + view + returns (uint256) + { + return _getIssuePremium(_setToken, _reserveAsset, _reserveAssetQuantity); + } + + function getRedeemPremium( + ISetToken _setToken, + address _reserveAsset, + uint256 _setTokenQuantity + ) + external + view + returns (uint256) + { + return _getRedeemPremium(_setToken, _reserveAsset, _setTokenQuantity); + } + + function getManagerFee(ISetToken _setToken, uint256 _managerFeeIndex) external view returns (uint256) { + return navIssuanceSettings[_setToken].managerFees[_managerFeeIndex]; + } + + /** + * Get the expected SetTokens minted to recipient on issuance + * + * @param _setToken Instance of the SetToken + * @param _reserveAsset Address of the reserve asset + * @param _reserveAssetQuantity Quantity of the reserve asset to issue with + * + * @return uint256 Expected SetTokens to be minted to recipient + */ + function getExpectedSetTokenIssueQuantity( + ISetToken _setToken, + address _reserveAsset, + uint256 _reserveAssetQuantity + ) + external + view + returns (uint256) + { + (,, uint256 netReserveFlow) = _getFees( + _setToken, + _reserveAssetQuantity, + PROTOCOL_ISSUE_MANAGER_REVENUE_SHARE_FEE_INDEX, + PROTOCOL_ISSUE_DIRECT_FEE_INDEX, + MANAGER_ISSUE_FEE_INDEX + ); + + uint256 setTotalSupply = _setToken.totalSupply(); + + return _getSetTokenMintQuantity( + _setToken, + _reserveAsset, + netReserveFlow, + setTotalSupply + ); + } + + /** + * Get the expected reserve asset to be redeemed + * + * @param _setToken Instance of the SetToken + * @param _reserveAsset Address of the reserve asset + * @param _setTokenQuantity Quantity of SetTokens to redeem + * + * @return uint256 Expected reserve asset quantity redeemed + */ + function getExpectedReserveRedeemQuantity( + ISetToken _setToken, + address _reserveAsset, + uint256 _setTokenQuantity + ) + external + view + returns (uint256) + { + uint256 preFeeReserveQuantity = _getRedeemReserveQuantity(_setToken, _reserveAsset, _setTokenQuantity); + + (,, uint256 netReserveFlows) = _getFees( + _setToken, + preFeeReserveQuantity, + PROTOCOL_REDEEM_MANAGER_REVENUE_SHARE_FEE_INDEX, + PROTOCOL_REDEEM_DIRECT_FEE_INDEX, + MANAGER_REDEEM_FEE_INDEX + ); + + return netReserveFlows; + } + + /** + * Checks if issue is valid + * + * @param _setToken Instance of the SetToken + * @param _reserveAsset Address of the reserve asset + * @param _reserveAssetQuantity Quantity of the reserve asset to issue with + * + * @return bool Returns true if issue is valid + */ + function isIssueValid( + ISetToken _setToken, + address _reserveAsset, + uint256 _reserveAssetQuantity + ) + external + view + returns (bool) + { + uint256 setTotalSupply = _setToken.totalSupply(); + + return _reserveAssetQuantity != 0 + && isReserveAsset[_setToken][_reserveAsset] + && setTotalSupply >= navIssuanceSettings[_setToken].minSetTokenSupply; + } + + /** + * Checks if redeem is valid + * + * @param _setToken Instance of the SetToken + * @param _reserveAsset Address of the reserve asset + * @param _setTokenQuantity Quantity of SetTokens to redeem + * + * @return bool Returns true if redeem is valid + */ + function isRedeemValid( + ISetToken _setToken, + address _reserveAsset, + uint256 _setTokenQuantity + ) + external + view + returns (bool) + { + uint256 setTotalSupply = _setToken.totalSupply(); + + if ( + _setTokenQuantity == 0 + || !isReserveAsset[_setToken][_reserveAsset] + || setTotalSupply < navIssuanceSettings[_setToken].minSetTokenSupply.add(_setTokenQuantity) + ) { + return false; + } else { + uint256 totalRedeemValue =_getRedeemReserveQuantity(_setToken, _reserveAsset, _setTokenQuantity); + + (,, uint256 expectedRedeemQuantity) = _getFees( + _setToken, + totalRedeemValue, + PROTOCOL_REDEEM_MANAGER_REVENUE_SHARE_FEE_INDEX, + PROTOCOL_REDEEM_DIRECT_FEE_INDEX, + MANAGER_REDEEM_FEE_INDEX + ); + + uint256 existingUnit = _setToken.getDefaultPositionRealUnit(_reserveAsset).toUint256(); + + return existingUnit.preciseMul(setTotalSupply) >= expectedRedeemQuantity; + } + } + + /* ============ Internal Functions ============ */ + + function _validateCommon(ISetToken _setToken, address _reserveAsset, uint256 _quantity) internal view { + require(_quantity > 0, "Quantity must be > 0"); + require(isReserveAsset[_setToken][_reserveAsset], "Must be valid reserve asset"); + } + + function _validateIssuanceInfo(ISetToken _setToken, uint256 _minSetTokenReceiveQuantity, ActionInfo memory _issueInfo) internal view { + // Check that total supply is greater than min supply needed for issuance + // Note: A min supply amount is needed to avoid division by 0 when SetToken supply is 0 + require( + _issueInfo.previousSetTokenSupply >= navIssuanceSettings[_setToken].minSetTokenSupply, + "Supply must be greater than minimum to enable issuance" + ); + + require(_issueInfo.setTokenQuantity >= _minSetTokenReceiveQuantity, "Must be greater than min SetToken"); + } + + function _validateRedemptionInfo( + ISetToken _setToken, + uint256 _minReserveReceiveQuantity, + ActionInfo memory _redeemInfo + ) + internal + view + { + // Check that new supply is more than min supply needed for redemption + // Note: A min supply amount is needed to avoid division by 0 when redeeming SetToken to 0 + require( + _redeemInfo.newSetTokenSupply >= navIssuanceSettings[_setToken].minSetTokenSupply, + "Supply must be greater than minimum to enable redemption" + ); + + require(_redeemInfo.netFlowQuantity >= _minReserveReceiveQuantity, "Must be greater than min receive reserve quantity"); + } + + function _createIssuanceInfo( + ISetToken _setToken, + address _reserveAsset, + uint256 _reserveAssetQuantity + ) + internal + view + returns (ActionInfo memory) + { + ActionInfo memory issueInfo; + + issueInfo.previousSetTokenSupply = _setToken.totalSupply(); + + issueInfo.preFeeReserveQuantity = _reserveAssetQuantity; + + (issueInfo.protocolFees, issueInfo.managerFee, issueInfo.netFlowQuantity) = _getFees( + _setToken, + issueInfo.preFeeReserveQuantity, + PROTOCOL_ISSUE_MANAGER_REVENUE_SHARE_FEE_INDEX, + PROTOCOL_ISSUE_DIRECT_FEE_INDEX, + MANAGER_ISSUE_FEE_INDEX + ); + + issueInfo.setTokenQuantity = _getSetTokenMintQuantity( + _setToken, + _reserveAsset, + issueInfo.netFlowQuantity, + issueInfo.previousSetTokenSupply + ); + + (issueInfo.newSetTokenSupply, issueInfo.newPositionMultiplier) = _getIssuePositionMultiplier(_setToken, issueInfo); + + issueInfo.newReservePositionUnit = _getIssuePositionUnit(_setToken, _reserveAsset, issueInfo); + + return issueInfo; + } + + function _createRedemptionInfo( + ISetToken _setToken, + address _reserveAsset, + uint256 _setTokenQuantity + ) + internal + view + returns (ActionInfo memory) + { + ActionInfo memory redeemInfo; + + redeemInfo.setTokenQuantity = _setTokenQuantity; + + redeemInfo.preFeeReserveQuantity =_getRedeemReserveQuantity(_setToken, _reserveAsset, _setTokenQuantity); + + (redeemInfo.protocolFees, redeemInfo.managerFee, redeemInfo.netFlowQuantity) = _getFees( + _setToken, + redeemInfo.preFeeReserveQuantity, + PROTOCOL_REDEEM_MANAGER_REVENUE_SHARE_FEE_INDEX, + PROTOCOL_REDEEM_DIRECT_FEE_INDEX, + MANAGER_REDEEM_FEE_INDEX + ); + + redeemInfo.previousSetTokenSupply = _setToken.totalSupply(); + + (redeemInfo.newSetTokenSupply, redeemInfo.newPositionMultiplier) = _getRedeemPositionMultiplier(_setToken, _setTokenQuantity, redeemInfo); + + redeemInfo.newReservePositionUnit = _getRedeemPositionUnit(_setToken, _reserveAsset, redeemInfo); + + return redeemInfo; + } + + /** + * Transfer reserve asset from user to SetToken and fees from user to appropriate fee recipients + */ + function _transferCollateralAndHandleFees(ISetToken _setToken, IERC20 _reserveAsset, ActionInfo memory _issueInfo) internal { + transferFrom(_reserveAsset, msg.sender, address(_setToken), _issueInfo.netFlowQuantity); + + if (_issueInfo.protocolFees > 0) { + transferFrom(_reserveAsset, msg.sender, controller.feeRecipient(), _issueInfo.protocolFees); + } + + if (_issueInfo.managerFee > 0) { + transferFrom(_reserveAsset, msg.sender, navIssuanceSettings[_setToken].feeRecipient, _issueInfo.managerFee); + } + } + + + /** + * Transfer WETH from module to SetToken and fees from module to appropriate fee recipients + */ + function _transferWETHAndHandleFees(ISetToken _setToken, ActionInfo memory _issueInfo) internal { + weth.transfer(address(_setToken), _issueInfo.netFlowQuantity); + + if (_issueInfo.protocolFees > 0) { + weth.transfer(controller.feeRecipient(), _issueInfo.protocolFees); + } + + if (_issueInfo.managerFee > 0) { + weth.transfer(navIssuanceSettings[_setToken].feeRecipient, _issueInfo.managerFee); + } + } + + function _handleIssueStateUpdates( + ISetToken _setToken, + address _reserveAsset, + address _to, + ActionInfo memory _issueInfo + ) + internal + { + _setToken.editPositionMultiplier(_issueInfo.newPositionMultiplier); + + _setToken.editDefaultPosition(_reserveAsset, _issueInfo.newReservePositionUnit); + + _setToken.mint(_to, _issueInfo.setTokenQuantity); + + emit SetTokenNAVIssued( + _setToken, + msg.sender, + _to, + _reserveAsset, + address(navIssuanceSettings[_setToken].managerIssuanceHook), + _issueInfo.setTokenQuantity, + _issueInfo.managerFee, + _issueInfo.protocolFees + ); + } + + function _handleRedeemStateUpdates( + ISetToken _setToken, + address _reserveAsset, + address _to, + ActionInfo memory _redeemInfo + ) + internal + { + _setToken.editPositionMultiplier(_redeemInfo.newPositionMultiplier); + + _setToken.editDefaultPosition(_reserveAsset, _redeemInfo.newReservePositionUnit); + + emit SetTokenNAVRedeemed( + _setToken, + msg.sender, + _to, + _reserveAsset, + address(navIssuanceSettings[_setToken].managerRedemptionHook), + _redeemInfo.setTokenQuantity, + _redeemInfo.managerFee, + _redeemInfo.protocolFees + ); + } + + function _handleRedemptionFees(ISetToken _setToken, address _reserveAsset, ActionInfo memory _redeemInfo) internal { + // Instruct the SetToken to transfer protocol fee to fee recipient if there is a fee + payProtocolFeeFromSetToken(_setToken, _reserveAsset, _redeemInfo.protocolFees); + + // Instruct the SetToken to transfer manager fee to manager fee recipient if there is a fee + if (_redeemInfo.managerFee > 0) { + _setToken.strictInvokeTransfer( + _reserveAsset, + navIssuanceSettings[_setToken].feeRecipient, + _redeemInfo.managerFee + ); + } + } + + /** + * Returns the issue premium percentage. Virtual function that can be overridden in future versions of the module + * and can contain arbitrary logic to calculate the issuance premium. + */ + function _getIssuePremium( + ISetToken _setToken, + address /* _reserveAsset */, + uint256 /* _reserveAssetQuantity */ + ) + virtual + internal + view + returns (uint256) + { + return navIssuanceSettings[_setToken].premiumPercentage; + } + + /** + * Returns the redeem premium percentage. Virtual function that can be overridden in future versions of the module + * and can contain arbitrary logic to calculate the redemption premium. + */ + function _getRedeemPremium( + ISetToken _setToken, + address /* _reserveAsset */, + uint256 /* _setTokenQuantity */ + ) + virtual + internal + view + returns (uint256) + { + return navIssuanceSettings[_setToken].premiumPercentage; + } + + /** + * Returns the fees attributed to the manager and the protocol. The fees are calculated as follows: + * + * ManagerFee = (manager fee % - % to protocol) * reserveAssetQuantity + * Protocol Fee = (% manager fee share + direct fee %) * reserveAssetQuantity + * + * @param _setToken Instance of the SetToken + * @param _reserveAssetQuantity Quantity of reserve asset to calculate fees from + * @param _protocolManagerFeeIndex Index to pull rev share NAV Issuance fee from the Controller + * @param _protocolDirectFeeIndex Index to pull direct NAV issuance fee from the Controller + * @param _managerFeeIndex Index from NAVIssuanceSettings (0 = issue fee, 1 = redeem fee) + * + * @return uint256 Fees paid to the protocol in reserve asset + * @return uint256 Fees paid to the manager in reserve asset + * @return uint256 Net reserve to user net of fees + */ + function _getFees( + ISetToken _setToken, + uint256 _reserveAssetQuantity, + uint256 _protocolManagerFeeIndex, + uint256 _protocolDirectFeeIndex, + uint256 _managerFeeIndex + ) + internal + view + returns (uint256, uint256, uint256) + { + (uint256 protocolFeePercentage, uint256 managerFeePercentage) = _getProtocolAndManagerFeePercentages( + _setToken, + _protocolManagerFeeIndex, + _protocolDirectFeeIndex, + _managerFeeIndex + ); + + // Calculate total notional fees + uint256 protocolFees = protocolFeePercentage.preciseMul(_reserveAssetQuantity); + uint256 managerFee = managerFeePercentage.preciseMul(_reserveAssetQuantity); + + uint256 netReserveFlow = _reserveAssetQuantity.sub(protocolFees).sub(managerFee); + + return (protocolFees, managerFee, netReserveFlow); + } + + function _getProtocolAndManagerFeePercentages( + ISetToken _setToken, + uint256 _protocolManagerFeeIndex, + uint256 _protocolDirectFeeIndex, + uint256 _managerFeeIndex + ) + internal + view + returns(uint256, uint256) + { + // Get protocol fee percentages + uint256 protocolDirectFeePercent = controller.getModuleFee(address(this), _protocolDirectFeeIndex); + uint256 protocolManagerShareFeePercent = controller.getModuleFee(address(this), _protocolManagerFeeIndex); + uint256 managerFeePercent = navIssuanceSettings[_setToken].managerFees[_managerFeeIndex]; + + // Calculate revenue share split percentage + uint256 protocolRevenueSharePercentage = protocolManagerShareFeePercent.preciseMul(managerFeePercent); + uint256 managerRevenueSharePercentage = managerFeePercent.sub(protocolRevenueSharePercentage); + uint256 totalProtocolFeePercentage = protocolRevenueSharePercentage.add(protocolDirectFeePercent); + + return (totalProtocolFeePercentage, managerRevenueSharePercentage); + } + + function _getSetTokenMintQuantity( + ISetToken _setToken, + address _reserveAsset, + uint256 _netReserveFlows, // Value of reserve asset net of fees + uint256 _setTotalSupply + ) + internal + view + returns (uint256) + { + uint256 premiumPercentage = _getIssuePremium(_setToken, _reserveAsset, _netReserveFlows); + uint256 premiumValue = _netReserveFlows.preciseMul(premiumPercentage); + + // If the set manager provided a custom valuer at initialization time, use it. Otherwise get it from the controller + // Get valuation of the SetToken with the quote asset as the reserve asset. Returns value in precise units (1e18) + // Reverts if price is not found + uint256 setTokenValuation = _getSetValuer(_setToken).calculateSetTokenValuation(_setToken, _reserveAsset); + + // Get reserve asset decimals + uint256 reserveAssetDecimals = ERC20(_reserveAsset).decimals(); + uint256 normalizedTotalReserveQuantityNetFees = _netReserveFlows.preciseDiv(10 ** reserveAssetDecimals); + uint256 normalizedTotalReserveQuantityNetFeesAndPremium = _netReserveFlows.sub(premiumValue).preciseDiv(10 ** reserveAssetDecimals); + + // Calculate SetTokens to mint to issuer + uint256 denominator = _setTotalSupply.preciseMul(setTokenValuation).add(normalizedTotalReserveQuantityNetFees).sub(normalizedTotalReserveQuantityNetFeesAndPremium); + return normalizedTotalReserveQuantityNetFeesAndPremium.preciseMul(_setTotalSupply).preciseDiv(denominator); + } + + function _getRedeemReserveQuantity( + ISetToken _setToken, + address _reserveAsset, + uint256 _setTokenQuantity + ) + internal + view + returns (uint256) + { + // Get valuation of the SetToken with the quote asset as the reserve asset. Returns value in precise units (10e18) + // Reverts if price is not found + uint256 setTokenValuation = _getSetValuer(_setToken).calculateSetTokenValuation(_setToken, _reserveAsset); + + uint256 totalRedeemValueInPreciseUnits = _setTokenQuantity.preciseMul(setTokenValuation); + // Get reserve asset decimals + uint256 reserveAssetDecimals = ERC20(_reserveAsset).decimals(); + uint256 prePremiumReserveQuantity = totalRedeemValueInPreciseUnits.preciseMul(10 ** reserveAssetDecimals); + + uint256 premiumPercentage = _getRedeemPremium(_setToken, _reserveAsset, _setTokenQuantity); + uint256 premiumQuantity = prePremiumReserveQuantity.preciseMulCeil(premiumPercentage); + + return prePremiumReserveQuantity.sub(premiumQuantity); + } + + /** + * The new position multiplier is calculated as follows: + * inflationPercentage = (newSupply - oldSupply) / newSupply + * newMultiplier = (1 - inflationPercentage) * positionMultiplier + */ + function _getIssuePositionMultiplier( + ISetToken _setToken, + ActionInfo memory _issueInfo + ) + internal + view + returns (uint256, int256) + { + // Calculate inflation and new position multiplier. Note: Round inflation up in order to round position multiplier down + uint256 newTotalSupply = _issueInfo.setTokenQuantity.add(_issueInfo.previousSetTokenSupply); + int256 newPositionMultiplier = _setToken.positionMultiplier() + .mul(_issueInfo.previousSetTokenSupply.toInt256()) + .div(newTotalSupply.toInt256()); + + return (newTotalSupply, newPositionMultiplier); + } + + /** + * Calculate deflation and new position multiplier. Note: Round deflation down in order to round position multiplier down + * + * The new position multiplier is calculated as follows: + * deflationPercentage = (oldSupply - newSupply) / newSupply + * newMultiplier = (1 + deflationPercentage) * positionMultiplier + */ + function _getRedeemPositionMultiplier( + ISetToken _setToken, + uint256 _setTokenQuantity, + ActionInfo memory _redeemInfo + ) + internal + view + returns (uint256, int256) + { + uint256 newTotalSupply = _redeemInfo.previousSetTokenSupply.sub(_setTokenQuantity); + int256 newPositionMultiplier = _setToken.positionMultiplier() + .mul(_redeemInfo.previousSetTokenSupply.toInt256()) + .div(newTotalSupply.toInt256()); + + return (newTotalSupply, newPositionMultiplier); + } + + /** + * The new position reserve asset unit is calculated as follows: + * totalReserve = (oldUnit * oldSetTokenSupply) + reserveQuantity + * newUnit = totalReserve / newSetTokenSupply + */ + function _getIssuePositionUnit( + ISetToken _setToken, + address _reserveAsset, + ActionInfo memory _issueInfo + ) + internal + view + returns (uint256) + { + uint256 existingUnit = _setToken.getDefaultPositionRealUnit(_reserveAsset).toUint256(); + uint256 totalReserve = existingUnit + .preciseMul(_issueInfo.previousSetTokenSupply) + .add(_issueInfo.netFlowQuantity); + + return totalReserve.preciseDiv(_issueInfo.newSetTokenSupply); + } + + /** + * The new position reserve asset unit is calculated as follows: + * totalReserve = (oldUnit * oldSetTokenSupply) - reserveQuantityToSendOut + * newUnit = totalReserve / newSetTokenSupply + */ + function _getRedeemPositionUnit( + ISetToken _setToken, + address _reserveAsset, + ActionInfo memory _redeemInfo + ) + internal + view + returns (uint256) + { + uint256 existingUnit = _setToken.getDefaultPositionRealUnit(_reserveAsset).toUint256(); + uint256 totalExistingUnits = existingUnit.preciseMul(_redeemInfo.previousSetTokenSupply); + + uint256 outflow = _redeemInfo.netFlowQuantity.add(_redeemInfo.protocolFees).add(_redeemInfo.managerFee); + + // Require withdrawable quantity is greater than existing collateral + require(totalExistingUnits >= outflow, "Must be greater than total available collateral"); + + return totalExistingUnits.sub(outflow).preciseDiv(_redeemInfo.newSetTokenSupply); + } + + /** + * If a pre-issue hook has been configured, call the external-protocol contract. Pre-issue hook logic + * can contain arbitrary logic including validations, external function calls, etc. + */ + function _callPreIssueHooks( + ISetToken _setToken, + address _reserveAsset, + uint256 _reserveAssetQuantity, + address _caller, + address _to + ) + internal + { + INAVIssuanceHook preIssueHook = navIssuanceSettings[_setToken].managerIssuanceHook; + if (address(preIssueHook) != address(0)) { + preIssueHook.invokePreIssueHook(_setToken, _reserveAsset, _reserveAssetQuantity, _caller, _to); + } + } + + /** + * If a pre-redeem hook has been configured, call the external-protocol contract. + */ + function _callPreRedeemHooks(ISetToken _setToken, uint256 _setQuantity, address _caller, address _to) internal { + INAVIssuanceHook preRedeemHook = navIssuanceSettings[_setToken].managerRedemptionHook; + if (address(preRedeemHook) != address(0)) { + preRedeemHook.invokePreRedeemHook(_setToken, _setQuantity, _caller, _to); + } + } + + /** + * If a custom set valuer has been configured, use it. Otherwise fetch the default one form the + * controller. + */ + function _getSetValuer(ISetToken _setToken) internal view returns (ISetValuer) { + ISetValuer customValuer = navIssuanceSettings[_setToken].setValuer; + return address(customValuer) == address(0) ? controller.getSetValuer() : customValuer; + } +} diff --git a/external/contracts/set/DebtIssuanceModuleV3.sol b/external/contracts/set/DebtIssuanceModuleV3.sol new file mode 100644 index 000000000..ddf0a1323 --- /dev/null +++ b/external/contracts/set/DebtIssuanceModuleV3.sol @@ -0,0 +1,202 @@ +/* + Copyright 2024 Index Coop + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache License, Version 2.0 +*/ + +pragma solidity 0.6.10; +pragma experimental "ABIEncoderV2"; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import { DebtIssuanceModuleV2 } from "./DebtIssuanceModuleV2.sol"; +import { IController } from "../../../interfaces/IController.sol"; +import { Invoke } from "../../lib/Invoke.sol"; +import { ISetToken } from "../../../interfaces/ISetToken.sol"; +import { IssuanceValidationUtils } from "../../lib/IssuanceValidationUtils.sol"; +import { Position } from "../../lib/Position.sol"; + + +/** + * @title DebtIssuanceModuleV3 + * @author Set Protocol + * + * This Module is an adjusted version of the DebtIssuanceModuleV2 + * to account for rounding errors in some tokens that mean balanceAfter != balanceBefore + amountTransferred + * To avoid undercollateralization errors we: + * - Subtract a few wei whenever transfering tokens to the user (debtTokens on issuance, equityTokens on redemption) + * - Add a few wei whenever transfering tokens to the SetToken (equityTokens on issuance, debtTokens on redemption) + * The amount to add/subtract is defined in the tokenTransferBuffer variable + * + */ +contract DebtIssuanceModuleV3 is DebtIssuanceModuleV2 { + using Position for uint256; + + // Amount in WEI by which we will adjust token transfers to avoid revertions on rounding errors + uint256 immutable public tokenTransferBuffer; + + /* ============ Constructor ============ */ + + constructor( + IController _controller, + uint256 _tokenTransferBuffer + ) public DebtIssuanceModuleV2(_controller) { + tokenTransferBuffer = _tokenTransferBuffer; + } + + /* ============ External View Functions ============ */ + + /** + * @dev Same as in v2 but adjusting the positions by the tokenTransferBuffer currently configured: + * - Increases equityPositions by configured tokenTransferBuffer (because they are transferred in) + * - Decreases debtPositions by configured tokenTransferBuffer (because they are transferred out) + * The original logic is factored out into the _getRequiredComponentIssuanceUnits internal helper method for readability + */ + function getRequiredComponentIssuanceUnits( + ISetToken _setToken, + uint256 _quantity + ) + external + view + override + returns (address[] memory components, uint256[] memory equityUnits, uint256[] memory debtUnits) + { + (components, equityUnits, debtUnits) = _getRequiredComponentIssuanceUnits(_setToken, _quantity); + for(uint256 i = 0; i < equityUnits.length; i++) { + if(equityUnits[i] > 0) { + equityUnits[i] += tokenTransferBuffer; + } + } + } + + /** + * @dev Same as in v2 but adjusting the positions by the tokenTransferBuffer currently configured + * - Increases debtPositions by configured tokenTransferBuffer (because they are transferred in) + * - Decreases equityPositions by configured tokenTransferBuffer (because they are transferred out) + */ + function getRequiredComponentRedemptionUnits( + ISetToken _setToken, + uint256 _quantity + ) + external + view + override + returns (address[] memory components, uint256[] memory equityUnits, uint256[] memory debtUnits) + { + ( + uint256 totalQuantity,, + ) = calculateTotalFees(_setToken, _quantity, false); + + (components, equityUnits, debtUnits) = _calculateRequiredComponentIssuanceUnits(_setToken, totalQuantity, false); + for(uint256 i = 0; i < equityUnits.length; i++) { + if(equityUnits[i] > tokenTransferBuffer) { + equityUnits[i] -= tokenTransferBuffer; + } else { + equityUnits[i] = 0; + } + } + } + + /* ============ Internal Functions ============ */ + + /** + * @dev Contains the exact same logic as DebtIssuanceModuleV2.getRequiredComponentIssuanceUnits + * @dev Factored out into internal helper method to keep the getRequiredComponentRedemptionUnits function more readable + */ + function _getRequiredComponentIssuanceUnits( + ISetToken _setToken, + uint256 _quantity + ) + internal + view + returns (address[] memory, uint256[] memory, uint256[] memory) + { + ( + uint256 totalQuantity,, + ) = calculateTotalFees(_setToken, _quantity, true); + + if(_setToken.totalSupply() == 0) { + return _calculateRequiredComponentIssuanceUnits(_setToken, totalQuantity, true); + } else { + ( + address[] memory components, + uint256[] memory equityUnits, + uint256[] memory debtUnits + ) = _getTotalIssuanceUnitsFromBalances(_setToken); + + uint256 componentsLength = components.length; + uint256[] memory totalEquityUnits = new uint256[](componentsLength); + uint256[] memory totalDebtUnits = new uint256[](componentsLength); + for (uint256 i = 0; i < components.length; i++) { + // Use preciseMulCeil to round up to ensure overcollateration of equity when small issue quantities are provided + // and use preciseMul to round debt calculations down to make sure we don't return too much debt to issuer + totalEquityUnits[i] = equityUnits[i].preciseMulCeil(totalQuantity); + totalDebtUnits[i] = debtUnits[i].preciseMul(totalQuantity); + } + + return (components, totalEquityUnits, totalDebtUnits); + } + } + + + /** + * @dev Same as in v2 but adjusting the token transfers by the tokenTransferBuffer (adding when transferring in, subtracting when transferring out) + */ + function _resolveEquityPositions( + ISetToken _setToken, + uint256 _quantity, + address _to, + bool _isIssue, + address[] memory _components, + uint256[] memory _componentEquityQuantities, + uint256 _initialSetSupply, + uint256 _finalSetSupply + ) + internal + override + { + for (uint256 i = 0; i < _components.length; i++) { + address component = _components[i]; + uint256 componentQuantity = _componentEquityQuantities[i]; + if (componentQuantity > 0) { + if (_isIssue) { + // Call SafeERC20#safeTransferFrom instead of ExplicitERC20#transferFrom + SafeERC20.safeTransferFrom( + IERC20(component), + msg.sender, + address(_setToken), + // Transfer in a few wei more than the calculated quantity to avoid undercollateralization in case of rounding error on the token + componentQuantity + tokenTransferBuffer + ); + + IssuanceValidationUtils.validateCollateralizationPostTransferInPreHook(_setToken, component, _initialSetSupply, componentQuantity); + + _executeExternalPositionHooks(_setToken, _quantity, IERC20(component), true, true); + } else { + _executeExternalPositionHooks(_setToken, _quantity, IERC20(component), false, true); + + // Call Invoke#invokeTransfer instead of Invoke#strictInvokeTransfer + + // Transfer out a few wei less than the calculated quantity to avoid undercollateralization in case of rounding error on the token + _setToken.invokeTransfer(component, _to, componentQuantity - tokenTransferBuffer); + + + IssuanceValidationUtils.validateCollateralizationPostTransferOut(_setToken, component, _finalSetSupply); + } + } + } + } +} diff --git a/external/contracts/set/ERC4626Oracle.sol b/external/contracts/set/ERC4626Oracle.sol new file mode 100644 index 000000000..0781ddb23 --- /dev/null +++ b/external/contracts/set/ERC4626Oracle.sol @@ -0,0 +1,59 @@ +/* + Copyright 2024 Index Cooperative + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache-2.0 +*/ + +pragma solidity 0.8.17; + +import { IERC4626 } from "../../../interfaces/external/IERC4626.sol"; + +/** + * @title ERC4626Oracle + * @author Index Cooperative + * + * Oracle built to retrieve the assets per one share of the ERC-4626 vault + */ +contract ERC4626Oracle { + IERC4626 public immutable vault; + uint256 public immutable underlyingFullUnit; + uint256 public immutable vaultFullUnit; + string public dataDescription; + + /* + * @param _vault The address of the ERC-4626 vault + * @param _underlyingFullUnit The full unit of the underlying asset + * @param _dataDescription Human readable description of oracle + */ + constructor( + IERC4626 _vault, + uint256 _underlyingFullUnit, + string memory _dataDescription + ) { + vault = _vault; + dataDescription = _dataDescription; + + underlyingFullUnit = _underlyingFullUnit; + vaultFullUnit = 10 ** _vault.decimals(); + } + + /** + * Returns the assets per one share of the vault + */ + function read() external view returns (uint256) { + uint256 assetsPerShare = vault.convertToAssets(vaultFullUnit); + return assetsPerShare * vaultFullUnit / underlyingFullUnit; + } +} diff --git a/external/contracts/set/OracleMock.sol b/external/contracts/set/OracleMock.sol new file mode 100644 index 000000000..e734c2049 --- /dev/null +++ b/external/contracts/set/OracleMock.sol @@ -0,0 +1,41 @@ +/* + Copyright 2020 Set Labs Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache License, Version 2.0 +*/ + +pragma solidity 0.6.10; + +contract OracleMock { + uint256 public price; + + constructor(uint256 _startingPrice) public { + price = _startingPrice; + } + + /* ============ External Functions ============ */ + function updatePrice(uint256 _newPrice) external { + price = _newPrice; + } + + /** + * Returns the queried data from an oracle returning uint256 + * + * @return Current price of asset represented in uint256 + */ + function read() external view returns (uint256) { + return price; + } +} \ No newline at end of file diff --git a/external/contracts/set/PreciseUnitOracle.sol b/external/contracts/set/PreciseUnitOracle.sol new file mode 100644 index 000000000..a7119db42 --- /dev/null +++ b/external/contracts/set/PreciseUnitOracle.sol @@ -0,0 +1,45 @@ +/* + Copyright 2024 Index Cooperative + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache-2.0 +*/ + +pragma solidity 0.6.10; + +import { PreciseUnitMath } from "../../../lib/PreciseUnitMath.sol"; + +/** + * @title PreciseUnitOracle + * @author Index Cooperative + * + * Oracle built to retrieve the precise unit as price, useful for rebasing tokens like aUSDC and USDC + */ +contract PreciseUnitOracle { + string public dataDescription; + + /* + * @param _dataDescription Human readable description of oracle + */ + constructor(string memory _dataDescription) public { + dataDescription = _dataDescription; + } + + /** + * Returns the assets per one share of the vault + */ + function read() external pure returns (uint256) { + return PreciseUnitMath.preciseUnit(); + } +} diff --git a/external/contracts/set/PriceOracle.sol b/external/contracts/set/PriceOracle.sol new file mode 100644 index 000000000..8a89381e1 --- /dev/null +++ b/external/contracts/set/PriceOracle.sol @@ -0,0 +1,356 @@ +/* + Copyright 2020 Set Labs Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache License, Version 2.0 +*/ + +pragma solidity 0.6.10; +pragma experimental "ABIEncoderV2"; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + +import { AddressArrayUtils } from "../lib/AddressArrayUtils.sol"; +import { IController } from "../interfaces/IController.sol"; +import { IOracle } from "../interfaces/IOracle.sol"; +import { IOracleAdapter } from "../interfaces/IOracleAdapter.sol"; +import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol"; + + +/** + * @title PriceOracle + * @author Set Protocol + * + * Contract that returns the price for any given asset pair. Price is retrieved either directly from an oracle, + * calculated using common asset pairs, or uses external data to calculate price. + * Note: Prices are returned in preciseUnits (i.e. 18 decimals of precision) + */ +contract PriceOracle is Ownable { + using PreciseUnitMath for uint256; + using AddressArrayUtils for address[]; + + /* ============ Events ============ */ + + event PairAdded(address indexed _assetOne, address indexed _assetTwo, address _oracle); + event PairRemoved(address indexed _assetOne, address indexed _assetTwo, address _oracle); + event PairEdited(address indexed _assetOne, address indexed _assetTwo, address _newOracle); + event AdapterAdded(address _adapter); + event AdapterRemoved(address _adapter); + event MasterQuoteAssetEdited(address _newMasterQuote); + + /* ============ State Variables ============ */ + + // Address of the Controller contract + IController public controller; + + // Mapping between assetA/assetB and its associated Price Oracle + // Asset 1 -> Asset 2 -> IOracle Interface + mapping(address => mapping(address => IOracle)) public oracles; + + // Token address of the bridge asset that prices are derived from if the specified pair price is missing + address public masterQuoteAsset; + + // List of IOracleAdapters used to return prices of third party protocols (e.g. Uniswap, Compound, Balancer) + address[] public adapters; + + /* ============ Constructor ============ */ + + /** + * Set state variables and map asset pairs to their oracles + * + * @param _controller Address of controller contract + * @param _masterQuoteAsset Address of asset that can be used to link unrelated asset pairs + * @param _adapters List of adapters used to price assets created by other protocols + * @param _assetOnes List of first asset in pair, index i maps to same index in assetTwos and oracles + * @param _assetTwos List of second asset in pair, index i maps to same index in assetOnes and oracles + * @param _oracles List of oracles, index i maps to same index in assetOnes and assetTwos + */ + constructor( + IController _controller, + address _masterQuoteAsset, + address[] memory _adapters, + address[] memory _assetOnes, + address[] memory _assetTwos, + IOracle[] memory _oracles + ) + public + { + controller = _controller; + masterQuoteAsset = _masterQuoteAsset; + adapters = _adapters; + require( + _assetOnes.length == _assetTwos.length && _assetTwos.length == _oracles.length, + "Array lengths do not match." + ); + + for (uint256 i = 0; i < _assetOnes.length; i++) { + oracles[_assetOnes[i]][_assetTwos[i]] = _oracles[i]; + } + } + + /* ============ External Functions ============ */ + + /** + * SYSTEM-ONLY PRIVELEGE: Find price of passed asset pair, if possible. The steps it takes are: + * 1) Check to see if a direct or inverse oracle of the pair exists, + * 2) If not, use masterQuoteAsset to link pairs together (i.e. BTC/ETH and ETH/USDC + * could be used to calculate BTC/USDC). + * 3) If not, check oracle adapters in case one or more of the assets needs external protocol data + * to price. + * 4) If all steps fail, revert. + * + * @param _assetOne Address of first asset in pair + * @param _assetTwo Address of second asset in pair + * @return Price of asset pair to 18 decimals of precision + */ + function getPrice(address _assetOne, address _assetTwo) external view returns (uint256) { + require( + controller.isSystemContract(msg.sender), + "PriceOracle.getPrice: Caller must be system contract." + ); + + bool priceFound; + uint256 price; + + (priceFound, price) = _getDirectOrInversePrice(_assetOne, _assetTwo); + + if (!priceFound) { + (priceFound, price) = _getPriceFromMasterQuote(_assetOne, _assetTwo); + } + + if (!priceFound) { + (priceFound, price) = _getPriceFromAdapters(_assetOne, _assetTwo); + } + + require(priceFound, "PriceOracle.getPrice: Price not found."); + + return price; + } + + /** + * GOVERNANCE FUNCTION: Add new asset pair oracle. + * + * @param _assetOne Address of first asset in pair + * @param _assetTwo Address of second asset in pair + * @param _oracle Address of asset pair's oracle + */ + function addPair(address _assetOne, address _assetTwo, IOracle _oracle) external onlyOwner { + require( + address(oracles[_assetOne][_assetTwo]) == address(0), + "PriceOracle.addPair: Pair already exists." + ); + oracles[_assetOne][_assetTwo] = _oracle; + + emit PairAdded(_assetOne, _assetTwo, address(_oracle)); + } + + /** + * GOVERNANCE FUNCTION: Edit an existing asset pair's oracle. + * + * @param _assetOne Address of first asset in pair + * @param _assetTwo Address of second asset in pair + * @param _oracle Address of asset pair's new oracle + */ + function editPair(address _assetOne, address _assetTwo, IOracle _oracle) external onlyOwner { + require( + address(oracles[_assetOne][_assetTwo]) != address(0), + "PriceOracle.editPair: Pair doesn't exist." + ); + oracles[_assetOne][_assetTwo] = _oracle; + + emit PairEdited(_assetOne, _assetTwo, address(_oracle)); + } + + /** + * GOVERNANCE FUNCTION: Remove asset pair's oracle. + * + * @param _assetOne Address of first asset in pair + * @param _assetTwo Address of second asset in pair + */ + function removePair(address _assetOne, address _assetTwo) external onlyOwner { + require( + address(oracles[_assetOne][_assetTwo]) != address(0), + "PriceOracle.removePair: Pair doesn't exist." + ); + IOracle oldOracle = oracles[_assetOne][_assetTwo]; + delete oracles[_assetOne][_assetTwo]; + + emit PairRemoved(_assetOne, _assetTwo, address(oldOracle)); + } + + /** + * GOVERNANCE FUNCTION: Add new oracle adapter. + * + * @param _adapter Address of new adapter + */ + function addAdapter(address _adapter) external onlyOwner { + require( + !adapters.contains(_adapter), + "PriceOracle.addAdapter: Adapter already exists." + ); + adapters.push(_adapter); + + emit AdapterAdded(_adapter); + } + + /** + * GOVERNANCE FUNCTION: Remove oracle adapter. + * + * @param _adapter Address of adapter to remove + */ + function removeAdapter(address _adapter) external onlyOwner { + require( + adapters.contains(_adapter), + "PriceOracle.removeAdapter: Adapter does not exist." + ); + adapters = adapters.remove(_adapter); + + emit AdapterRemoved(_adapter); + } + + /** + * GOVERNANCE FUNCTION: Change the master quote asset. + * + * @param _newMasterQuoteAsset New address of master quote asset + */ + function editMasterQuoteAsset(address _newMasterQuoteAsset) external onlyOwner { + masterQuoteAsset = _newMasterQuoteAsset; + + emit MasterQuoteAssetEdited(_newMasterQuoteAsset); + } + + /* ============ External View Functions ============ */ + + /** + * Returns an array of adapters + */ + function getAdapters() external view returns (address[] memory) { + return adapters; + } + + /* ============ Internal Functions ============ */ + + /** + * Check if direct or inverse oracle exists. If so return that price along with boolean indicating + * it exists. Otherwise return boolean indicating oracle doesn't exist. + * + * @param _assetOne Address of first asset in pair + * @param _assetTwo Address of second asset in pair + * @return bool Boolean indicating if oracle exists + * @return uint256 Price of asset pair to 18 decimal precision (if exists, otherwise 0) + */ + function _getDirectOrInversePrice( + address _assetOne, + address _assetTwo + ) + internal + view + returns (bool, uint256) + { + IOracle directOracle = oracles[_assetOne][_assetTwo]; + bool hasDirectOracle = address(directOracle) != address(0); + + // Check asset1 -> asset 2. If exists, then return value + if (hasDirectOracle) { + return (true, directOracle.read()); + } + + IOracle inverseOracle = oracles[_assetTwo][_assetOne]; + bool hasInverseOracle = address(inverseOracle) != address(0); + + // If not, check asset 2 -> asset 1. If exists, then return 1 / asset1 -> asset2 + if (hasInverseOracle) { + return (true, _calculateInversePrice(inverseOracle)); + } + + return (false, 0); + } + + /** + * Try to calculate asset pair price by getting each asset in the pair's price relative to master + * quote asset. Both prices must exist otherwise function returns false and no price. + * + * @param _assetOne Address of first asset in pair + * @param _assetTwo Address of second asset in pair + * @return bool Boolean indicating if oracle exists + * @return uint256 Price of asset pair to 18 decimal precision (if exists, otherwise 0) + */ + function _getPriceFromMasterQuote( + address _assetOne, + address _assetTwo + ) + internal + view + returns (bool, uint256) + { + ( + bool priceFoundOne, + uint256 assetOnePrice + ) = _getDirectOrInversePrice(_assetOne, masterQuoteAsset); + + ( + bool priceFoundTwo, + uint256 assetTwoPrice + ) = _getDirectOrInversePrice(_assetTwo, masterQuoteAsset); + + if (priceFoundOne && priceFoundTwo) { + return (true, assetOnePrice.preciseDiv(assetTwoPrice)); + } + + return (false, 0); + } + + /** + * Scan adapters to see if one or more of the assets needs external protocol data to be priced. If + * does not exist return false and no price. + * + * @param _assetOne Address of first asset in pair + * @param _assetTwo Address of second asset in pair + * @return bool Boolean indicating if oracle exists + * @return uint256 Price of asset pair to 18 decimal precision (if exists, otherwise 0) + */ + function _getPriceFromAdapters( + address _assetOne, + address _assetTwo + ) + internal + view + returns (bool, uint256) + { + for (uint256 i = 0; i < adapters.length; i++) { + ( + bool priceFound, + uint256 price + ) = IOracleAdapter(adapters[i]).getPrice(_assetOne, _assetTwo); + + if (priceFound) { + return (priceFound, price); + } + } + + return (false, 0); + } + + /** + * Calculate inverse price of passed oracle. The inverse price is 1 (or 1e18) / inverse price + * + * @param _inverseOracle Address of oracle to invert + * @return uint256 Inverted price of asset pair to 18 decimal precision + */ + function _calculateInversePrice(IOracle _inverseOracle) internal view returns(uint256) { + uint256 inverseValue = _inverseOracle.read(); + + return PreciseUnitMath.preciseUnit().preciseDiv(inverseValue); + } +} diff --git a/external/contracts/set/RebasingComponentModule.sol b/external/contracts/set/RebasingComponentModule.sol new file mode 100644 index 000000000..81dfc2964 --- /dev/null +++ b/external/contracts/set/RebasingComponentModule.sol @@ -0,0 +1,277 @@ +/* + Copyright 2024 Index Coop + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache License, Version 2.0 +*/ + +pragma solidity 0.6.10; +pragma experimental "ABIEncoderV2"; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; + +import { IController } from "../../../interfaces/IController.sol"; +import { IDebtIssuanceModule } from "../../../interfaces/IDebtIssuanceModule.sol"; +import { IModuleIssuanceHook } from "../../../interfaces/IModuleIssuanceHook.sol"; +import { INAVIssuanceHook } from "../../../interfaces/INAVIssuanceHook.sol"; +import { ISetToken } from "../../../interfaces/ISetToken.sol"; +import { ModuleBase } from "../../lib/ModuleBase.sol"; + +/** + * @title RebasingComponentModule + * @author Index Coop + * @notice Module for syncing rebasing components before issuance and redemption via DebtIssuanceModule and NAVIssuanceModule. + */ +contract RebasingComponentModule is ModuleBase, ReentrancyGuard, Ownable, IModuleIssuanceHook, INAVIssuanceHook { + + /* ============ Events ============ */ + + /** + * @dev Emitted when rebasing components are added or removed. + * @param _setToken Instance of SetToken whose rebasing components are updated. + * @param _isAdded True if components are added, false if removed. + * @param _components Array of rebasing components being added/removed. + */ + event RebasingComponentsUpdated( + ISetToken indexed _setToken, + bool indexed _isAdded, + IERC20[] _components + ); + + /* ============ State Variables ============ */ + + // Mapping to efficiently check if rebasing component is enabled in SetToken + mapping(ISetToken => mapping(IERC20 => bool)) public rebasingComponentEnabled; + + // Internal mapping of enabled rebasing components for syncing positions + mapping(ISetToken => address[]) internal rebasingComponents; + + /* ============ Constructor ============ */ + + /** + * @dev Initializes the module with the controller address. + * @param _controller Address of the controller contract. + */ + constructor(IController _controller) public ModuleBase(_controller) { } + + /* ============ External Functions ============ */ + + /** + * @dev CALLABLE BY ANYBODY: Sync Set positions with ALL enabled rebasing component positions. + * @param _setToken Instance of the SetToken + */ + function sync(ISetToken _setToken) public nonReentrant onlyValidAndInitializedSet(_setToken) { + uint256 setTotalSupply = _setToken.totalSupply(); + + // Only sync positions when Set supply is not 0. Without this check, if sync is called by someone before the + // first issuance, then editDefaultPosition would remove the default positions from the SetToken + if (setTotalSupply > 0) { + address[] memory setTokenRebasingComponents = rebasingComponents[_setToken]; + for (uint256 i = 0; i < setTokenRebasingComponents.length; i++) { + IERC20 component = IERC20(setTokenRebasingComponents[i]); + + uint256 previousPositionUnit = _setToken.getDefaultPositionRealUnit(address(component)).toUint256(); + uint256 newPositionUnit = component.balanceOf(address(_setToken)).preciseDiv(setTotalSupply); + + // Note: Accounts for if position does not exist on SetToken but is tracked in rebasingComponents + if (previousPositionUnit != newPositionUnit) { + _setToken.editDefaultPosition(address(component), newPositionUnit); + } + } + } + } + + /** + * @dev MANAGER ONLY: Initializes this module to the SetToken. Only callable by the SetToken's manager. + * Note: Managers can enable rebasing components that don't exist as positions on the SetToken + * @param _setToken Instance of the SetToken to initialize + * @param _rebasingComponents Rebasing components to be enabled in the SetToken + */ + function initialize( + ISetToken _setToken, + IERC20[] memory _rebasingComponents + ) + external + onlySetManager(_setToken, msg.sender) + onlyValidAndPendingSet(_setToken) + { + // Initialize module before trying register + _setToken.initializeModule(); + + // Try if register exists on any of the modules including the debt issuance module + address[] memory modules = _setToken.getModules(); + for(uint256 i = 0; i < modules.length; i++) { + try IDebtIssuanceModule(modules[i]).registerToIssuanceModule(_setToken) {} catch {} + } + + _addRebasingComponents(_setToken, _rebasingComponents); + } + + /** + * @dev MANAGER ONLY: Removes this module from the SetToken, via call by the SetToken. + */ + function removeModule() external override onlyValidAndInitializedSet(ISetToken(msg.sender)) { + ISetToken setToken = ISetToken(msg.sender); + + // Sync Aave and SetToken positions prior to any removal action + sync(setToken); + + address[] memory components = rebasingComponents[setToken]; + for(uint256 i = 0; i < components.length; i++) { + IERC20 component = IERC20(components[i]); + delete rebasingComponentEnabled[setToken][component]; + } + delete rebasingComponents[setToken]; + + // Try if unregister exists on any of the modules + address[] memory modules = setToken.getModules(); + for(uint256 i = 0; i < modules.length; i++) { + try IDebtIssuanceModule(modules[i]).unregisterFromIssuanceModule(setToken) {} catch {} + } + } + + /** + * @dev MANAGER ONLY: Add registration of this module on the debt issuance module for the SetToken. + * Note: if the debt issuance module is not added to SetToken before this module is initialized, then this function + * needs to be called if the debt issuance module is later added and initialized to prevent state inconsistencies + * @param _setToken Instance of the SetToken + * @param _debtIssuanceModule Debt issuance module address to register + */ + function registerToModule(ISetToken _setToken, IDebtIssuanceModule _debtIssuanceModule) external onlyManagerAndValidSet(_setToken) { + require(_setToken.isInitializedModule(address(_debtIssuanceModule)), "Issuance not initialized"); + + _debtIssuanceModule.registerToIssuanceModule(_setToken); + } + + /** + * @dev MANAGER ONLY: Add rebasing components. Rebasing components are tracked for syncing positions. + * + * NOTE: ALL ADDED REBASING COMPONENTS CAN BE ADDED AS A POSITION ON THE SET TOKEN WITHOUT MANAGER'S EXPLICIT PERMISSION. + * UNWANTED EXTRA POSITIONS CAN BREAK EXTERNAL LOGIC, INCREASE COST OF MINT/REDEEM OF SET TOKEN, AMONG OTHER POTENTIAL UNINTENDED CONSEQUENCES. + * SO, PLEASE ADD ONLY THOSE REBASING COMPONENTS WHOSE CORRESPONDING POSITIONS ARE NEEDED AS DEFAULT POSITIONS ON THE SET TOKEN. + * + * @param _setToken Instance of the SetToken + * @param _newRebasingComponents Addresses of new rebasing components + */ + function addRebasingComponents(ISetToken _setToken, IERC20[] memory _newRebasingComponents) external onlyManagerAndValidSet(_setToken) { + _addRebasingComponents(_setToken, _newRebasingComponents); + } + + /** + * @dev MANAGER ONLY: Remove rebasing components. + * @param _setToken Instance of the SetToken + * @param _rebasingComponents Addresses of rebasing components to remove + */ + function removeRebasingComponents(ISetToken _setToken, IERC20[] memory _rebasingComponents) external onlyManagerAndValidSet(_setToken) { + for(uint256 i = 0; i < _rebasingComponents.length; i++) { + IERC20 component = _rebasingComponents[i]; + require(rebasingComponentEnabled[_setToken][component], "Rebasing component not enabled"); + + delete rebasingComponentEnabled[_setToken][component]; + rebasingComponents[_setToken].removeStorage(address(component)); + } + emit RebasingComponentsUpdated(_setToken, false, _rebasingComponents); + } + + /** + * @dev MODULE ONLY: Hook called prior to debt issuance module issuance to sync rebasing components position on SetToken. + * @param _setToken Instance of the SetToken + */ + function moduleIssueHook(ISetToken _setToken, uint256 /* _setTokenQuantity */) external override onlyModule(_setToken) { + sync(_setToken); + } + + /** + * @dev MODULE ONLY: Hook called prior to debt issuance module redemption to sync rebasing components position on SetToken. + * @param _setToken Instance of the SetToken + */ + function moduleRedeemHook(ISetToken _setToken, uint256 /* _setTokenQuantity */) external override onlyModule(_setToken) { + sync(_setToken); + } + + /** + * @dev MODULE ONLY: Hook called prior to looping through each component on issuance. Only callable by valid module. + */ + function componentIssueHook(ISetToken _setToken, uint256 /* _setTokenQuantity */, IERC20 /* _component */, bool /* _isEquity */) external override onlyModule(_setToken) { } + + /** + * @dev MODULE ONLY: Hook called prior to looping through each component on redemption. Only callable by valid module. + */ + function componentRedeemHook(ISetToken _setToken, uint256 /* _setTokenQuantity */, IERC20 /* _component */, bool /* _isEquity */) external override onlyModule(_setToken) { } + + /** + * @dev MODULE ONLY: Hook called prior to NAV issuance to sync rebasing components position on SetToken. + * @param _setToken Instance of the SetToken + */ + function invokePreIssueHook( + ISetToken _setToken, + address /* _reserveAsset */, + uint256 /* _reserveAssetQuantity */, + address /* _sender */, + address /* _to */ + ) + external + override + onlyModule(_setToken) + { + sync(_setToken); + } + + /** + * @dev MODULE ONLY: Hook called prior to NAV redemption. + * @param _setToken Instance of the SetToken + */ + function invokePreRedeemHook( + ISetToken _setToken, + uint256 /* _redeemQuantity */, + address /* _sender */, + address /* _to */ + ) + external + override + onlyModule(_setToken) + { + sync(_setToken); + } + + /* ============ External Getter Functions ============ */ + + /** + * @dev Get rebasing components for SetToken. Returns an array of rebasing components. + * @return Rebasing components that are enabled + */ + function getRebasingComponents(ISetToken _setToken) external view returns(address[] memory) { + return rebasingComponents[_setToken]; + } + + /* ============ Internal Functions ============ */ + + /** + * @dev Add rebasing components to SetToken. Updates the rebasingComponentsEnabled and rebasingComponents mappings. + * Emits RebasingComponentUpdated event. + */ + function _addRebasingComponents(ISetToken _setToken, IERC20[] memory _newRebasingComponents) internal { + for(uint256 i = 0; i < _newRebasingComponents.length; i++) { + IERC20 component = _newRebasingComponents[i]; + + require(!rebasingComponentEnabled[_setToken][component], "Rebasing component already enabled"); + + rebasingComponentEnabled[_setToken][component] = true; + rebasingComponents[_setToken].push(address(component)); + } + emit RebasingComponentsUpdated(_setToken, true, _newRebasingComponents); + } +} diff --git a/external/contracts/set/SetValuer.sol b/external/contracts/set/SetValuer.sol new file mode 100644 index 000000000..9849c3e4b --- /dev/null +++ b/external/contracts/set/SetValuer.sol @@ -0,0 +1,155 @@ +/* + Copyright 2020 Set Labs Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache License, Version 2.0 +*/ + +pragma solidity 0.6.10; +pragma experimental "ABIEncoderV2"; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol"; +import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol"; + +import { IController } from "../interfaces/IController.sol"; +import { ISetToken } from "../interfaces/ISetToken.sol"; +import { IPriceOracle } from "../interfaces/IPriceOracle.sol"; +import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol"; +import { Position } from "./lib/Position.sol"; +import { ResourceIdentifier } from "./lib/ResourceIdentifier.sol"; + + +/** + * @title SetValuer + * @author Set Protocol + * + * Contract that returns the valuation of SetTokens using price oracle data used in contracts + * that are external to the system. + * + * Note: Prices are returned in preciseUnits (i.e. 18 decimals of precision) + * + * CHANGELOG: + * - 2024-08: Add calculateComponentValuation function + */ +contract SetValuer { + using PreciseUnitMath for int256; + using PreciseUnitMath for uint256; + using Position for ISetToken; + using ResourceIdentifier for IController; + using SafeCast for int256; + using SafeCast for uint256; + using SignedSafeMath for int256; + + /* ============ State Variables ============ */ + + // Instance of the Controller contract + IController public controller; + + /* ============ Constructor ============ */ + + /** + * Set state variables and map asset pairs to their oracles + * + * @param _controller Address of controller contract + */ + constructor(IController _controller) public { + controller = _controller; + } + + /* ============ External Functions ============ */ + + /** + * Gets the valuation of a SetToken using data from the price oracle. Reverts + * if no price exists for a component in the SetToken. Note: this works for external + * positions and negative (debt) positions. + * + * Note: There is a risk that the valuation is off if airdrops aren't retrieved or + * debt builds up via interest and its not reflected in the position + * + * @param _setToken SetToken instance to get valuation + * @param _quoteAsset Address of token to quote valuation in + * + * @return SetToken valuation in terms of quote asset in precise units 1e18 + */ + function calculateSetTokenValuation(ISetToken _setToken, address _quoteAsset) external view returns (uint256) { + IPriceOracle priceOracle = controller.getPriceOracle(); + address masterQuoteAsset = priceOracle.masterQuoteAsset(); + address[] memory components = _setToken.getComponents(); + int256 valuation; + + for (uint256 i = 0; i < components.length; i++) { + address component = components[i]; + // Get component price from price oracle. If price does not exist, revert. + uint256 componentPrice = priceOracle.getPrice(component, masterQuoteAsset); + + int256 aggregateUnits = _setToken.getTotalComponentRealUnits(component); + + // Normalize each position unit to preciseUnits 1e18 and cast to signed int + uint256 unitDecimals = ERC20(component).decimals(); + uint256 baseUnits = 10 ** unitDecimals; + int256 normalizedUnits = aggregateUnits.preciseDiv(baseUnits.toInt256()); + + // Calculate valuation of the component. Debt positions are effectively subtracted + valuation = normalizedUnits.preciseMul(componentPrice.toInt256()).add(valuation); + } + + if (masterQuoteAsset != _quoteAsset) { + uint256 quoteToMaster = priceOracle.getPrice(_quoteAsset, masterQuoteAsset); + valuation = valuation.preciseDiv(quoteToMaster.toInt256()); + } + + return valuation.toUint256(); + } + + /** + * Gets the valuation of a component in a SetToken using data from the price oracle. Reverts + * if no price exists for the component in the SetToken. Note: this works for external + * positions and negative (debt) positions. + * + * Note: There is a risk that the valuation is off if airdrops aren't retrieved or + * debt builds up via interest and its not reflected in the position + * + * @param _setToken SetToken instance to get valuation + * @param _component Address of component to get valuation + * @param _quoteAsset Address of token to quote valuation in + * + * @return SetToken's component valuation in terms of quote asset in precise units 1e18 + */ + function calculateComponentValuation(ISetToken _setToken, address _component, address _quoteAsset) external view returns (uint256) { + require(_setToken.isComponent(_component), "Component not in SetToken"); + + IPriceOracle priceOracle = controller.getPriceOracle(); + address masterQuoteAsset = priceOracle.masterQuoteAsset(); + int256 valuation; + + uint256 componentPrice = priceOracle.getPrice(_component, masterQuoteAsset); + + int256 aggregateUnits = _setToken.getTotalComponentRealUnits(_component); + + // Normalize each position unit to preciseUnits 1e18 and cast to signed int + uint256 unitDecimals = ERC20(_component).decimals(); + uint256 baseUnits = 10 ** unitDecimals; + int256 normalizedUnits = aggregateUnits.preciseDiv(baseUnits.toInt256()); + + valuation = normalizedUnits.preciseMul(componentPrice.toInt256()); + + if (masterQuoteAsset != _quoteAsset) { + uint256 quoteToMaster = priceOracle.getPrice(_quoteAsset, masterQuoteAsset); + valuation = valuation.preciseDiv(quoteToMaster.toInt256()); + } + + return valuation.toUint256(); + } +} diff --git a/utils/contracts/setV2.ts b/utils/contracts/setV2.ts index 91c39c8da..59b7be57c 100644 --- a/utils/contracts/setV2.ts +++ b/utils/contracts/setV2.ts @@ -28,3 +28,11 @@ export { WrapV2AdapterMock } from "../../typechain/WrapV2AdapterMock"; export { ClaimModule } from "../../typechain/ClaimModule"; export { ClaimAdapterMock } from "../../typechain/ClaimAdapterMock"; export { TradeModule } from "../../typechain/TradeModule"; +export { CustomOracleNavIssuanceModule } from "../../typechain/CustomOracleNavIssuanceModule"; +export { DebtIssuanceModuleV3 } from "../../typechain/DebtIssuanceModuleV3"; +export { ERC4626Oracle } from "../../typechain/ERC4626Oracle"; +export { OracleMock } from "../../typechain/OracleMock"; +export { PreciseUnitOracle } from "../../typechain/PreciseUnitOracle"; +export { PriceOracle } from "../../typechain/PriceOracle"; +export { RebasingComponentModule } from "../../typechain/RebasingComponentModule"; +export { SetValuer } from "../../typechain/SetValuer"; diff --git a/utils/deploys/deploySetV2.ts b/utils/deploys/deploySetV2.ts index ed6374ac6..f705dcaf6 100644 --- a/utils/deploys/deploySetV2.ts +++ b/utils/deploys/deploySetV2.ts @@ -16,15 +16,23 @@ import { ContractCallerMock, ClaimAdapterMock, ClaimModule, + CustomOracleNavIssuanceModule, DebtIssuanceModule, DebtIssuanceModuleV2, + DebtIssuanceModuleV3, + ERC4626Oracle, GeneralIndexModule, GovernanceModule, IntegrationRegistry, + OracleMock, + PreciseUnitOracle, + PriceOracle, + RebasingComponentModule, StreamingFeeModule, SetToken, TradeModule, SetTokenCreator, + SetValuer, SingleIndexModule, UniswapV2ExchangeAdapter, WrapModule, @@ -54,15 +62,23 @@ import { ComptrollerMock__factory } from "../../typechain/factories/ComptrollerM import { ContractCallerMock__factory } from "../../typechain/factories/ContractCallerMock__factory"; import { ClaimAdapterMock__factory } from "../../typechain/factories/ClaimAdapterMock__factory"; import { ClaimModule__factory } from "../../typechain/factories/ClaimModule__factory"; +import { CustomOracleNavIssuanceModule__factory } from "../../typechain/factories/CustomOracleNavIssuanceModule__factory"; import { DebtIssuanceModule__factory } from "../../typechain/factories/DebtIssuanceModule__factory"; import { DebtIssuanceModuleV2__factory } from "../../typechain/factories/DebtIssuanceModuleV2__factory"; +import { DebtIssuanceModuleV3__factory } from "../../typechain/factories/DebtIssuanceModuleV3__factory"; +import { ERC4626Oracle__factory } from "../../typechain/factories/ERC4626Oracle__factory"; import { GeneralIndexModule__factory } from "../../typechain/factories/GeneralIndexModule__factory"; import { GovernanceModule__factory } from "../../typechain/factories/GovernanceModule__factory"; import { IntegrationRegistry__factory } from "../../typechain/factories/IntegrationRegistry__factory"; +import { OracleMock__factory } from "../../typechain/factories/OracleMock__factory"; +import { PreciseUnitOracle__factory } from "../../typechain/factories/PreciseUnitOracle__factory"; +import { PriceOracle__factory } from "../../typechain/factories/PriceOracle__factory"; +import { RebasingComponentModule__factory } from "../../typechain/factories/RebasingComponentModule__factory"; import { SingleIndexModule__factory } from "../../typechain/factories/SingleIndexModule__factory"; import { StreamingFeeModule__factory } from "../../typechain/factories/StreamingFeeModule__factory"; import { SetToken__factory } from "../../typechain/factories/SetToken__factory"; import { SetTokenCreator__factory } from "../../typechain/factories/SetTokenCreator__factory"; +import { SetValuer__factory } from "../../typechain/factories/SetValuer__factory"; import { StandardTokenMock__factory } from "../../typechain/factories/StandardTokenMock__factory"; import { UniswapV2ExchangeAdapter__factory } from "../../typechain/factories/UniswapV2ExchangeAdapter__factory"; import { WETH9__factory } from "../../typechain/factories/WETH9__factory"; @@ -327,4 +343,64 @@ export default class DeploySetV2 { public async deployTradeModule(controller: Address): Promise { return await new TradeModule__factory(this._deployerSigner).deploy(controller); } + + public async deployCustomOracleNavIssuanceModule( + controller: Address, + weth: Address, + ): Promise { + return await new CustomOracleNavIssuanceModule__factory(this._deployerSigner).deploy( + controller, + weth, + ); + } + + public async deployDebtIssuanceModuleV3(controller: Address, tokenTransferBuffer: BigNumberish): Promise { + return await new DebtIssuanceModuleV3__factory(this._deployerSigner).deploy(controller, tokenTransferBuffer); + } + + public async deployERC4626Oracle( + vault: Address, + underlyingFullUnit: BigNumber, + dataDescription: string): Promise { + return await new ERC4626Oracle__factory(this._deployerSigner).deploy(vault, underlyingFullUnit, dataDescription); + } + + public async deployOracleMock(initialValue: BigNumberish): Promise { + return await new OracleMock__factory(this._deployerSigner).deploy(initialValue); + } + + public async deployPreciseUnitOracle( + dataDescription: string): Promise { + return await new PreciseUnitOracle__factory(this._deployerSigner).deploy(dataDescription); + } + + public async deployRebasingComponentModule(controller: Address): Promise { + return await new RebasingComponentModule__factory(this._deployerSigner).deploy(controller); + } + + public async deployPriceOracle( + controller: Address, + masterQuoteAsset: Address, + adapters: Address[], + assetOnes: Address[], + assetTwos: Address[], + oracles: Address[], + ): Promise { + return await new PriceOracle__factory(this._deployerSigner).deploy( + controller, + masterQuoteAsset, + adapters, + assetOnes, + assetTwos, + oracles, + ); + } + + public async getPriceOracle(priceOracleAddress: Address): Promise { + return await new PriceOracle__factory(this._deployerSigner).attach(priceOracleAddress); + } + + public async deploySetValuer(controller: Address): Promise { + return await new SetValuer__factory(this._deployerSigner).deploy(controller); + } } diff --git a/utils/fixtures/setFixture.ts b/utils/fixtures/setFixture.ts index fe7ae177b..40329deca 100644 --- a/utils/fixtures/setFixture.ts +++ b/utils/fixtures/setFixture.ts @@ -8,12 +8,17 @@ import { BasicIssuanceModule, CompoundLeverageModule, Controller, + CustomOracleNavIssuanceModule, DebtIssuanceModule, + DebtIssuanceModuleV3, GeneralIndexModule, GovernanceModule, IntegrationRegistry, + OracleMock, + PriceOracle, SetToken, SetTokenCreator, + SetValuer, SlippageIssuanceModule, StreamingFeeModule, WrapModule @@ -43,11 +48,15 @@ export class SetFixture { public controller: Controller; public factory: SetTokenCreator; + public priceOracle: PriceOracle; public integrationRegistry: IntegrationRegistry; + public setValuer: SetValuer; public auctionModule: AuctionRebalanceModuleV1; public issuanceModule: BasicIssuanceModule; + public navIssuanceModule: CustomOracleNavIssuanceModule; public debtIssuanceModule: DebtIssuanceModule; + public debtIssuanceModuleV3: DebtIssuanceModuleV3; public streamingFeeModule: StreamingFeeModule; public compoundLeverageModule: CompoundLeverageModule; public governanceModule: GovernanceModule; @@ -62,6 +71,16 @@ export class SetFixture { public dai: StandardTokenMock; public usdt: StandardTokenMock; + public ETH_USD_Oracle: OracleMock; + public USD_USD_Oracle: OracleMock; + public BTC_USD_Oracle: OracleMock; + public DAI_USD_Oracle: OracleMock; + + public component1Price: BigNumber; + public component2Price: BigNumber; + public component3Price: BigNumber; + public component4Price: BigNumber; + constructor(provider: Web3Provider | JsonRpcProvider, ownerAddress: Address) { this._provider = provider; this._ownerAddress = ownerAddress; @@ -84,9 +103,26 @@ export class SetFixture { this.governanceModule = await this._deployer.setV2.deployGovernanceModule(this.controller.address); this.airdropModule = await this._deployer.setV2.deployAirdropModule(this.controller.address); this.slippageIssuanceModule = await this._deployer.setV2.deploySlippageIssuanceModule(this.controller.address); + this.debtIssuanceModuleV3 = await this._deployer.setV2.deployDebtIssuanceModuleV3(this.controller.address, 10); await this.initializeStandardComponents(); + this.priceOracle = await this._deployer.setV2.deployPriceOracle( + this.controller.address, + this.usdc.address, + [], + [this.weth.address, this.usdc.address, this.wbtc.address, this.dai.address], + [this.usdc.address, this.usdc.address, this.usdc.address, this.usdc.address], + [ + this.ETH_USD_Oracle.address, + this.USD_USD_Oracle.address, + this.BTC_USD_Oracle.address, + this.DAI_USD_Oracle.address, + ] + ); + this.setValuer = await this._deployer.setV2.deploySetValuer(this.controller.address); + this.navIssuanceModule = await this._deployer.setV2.deployCustomOracleNavIssuanceModule(this.controller.address, this.weth.address); + this.generalIndexModule = await this._deployer.setV2.deployGeneralIndexModule( this.controller.address, this.weth.address @@ -107,13 +143,15 @@ export class SetFixture { this.airdropModule.address, this.wrapModule.address, this.slippageIssuanceModule.address, + this.navIssuanceModule.address, + this.debtIssuanceModuleV3.address, ]; await this.controller.initialize( [this.factory.address], // Factories modules, // Modules - [this.integrationRegistry.address], // Resources - [0] + [this.integrationRegistry.address, this.priceOracle.address, this.setValuer.address], // Resources + [0, 1, 2] // Resource IDs where IntegrationRegistry is 0, PriceOracle is 1, SetValuer is 2 ); } @@ -124,6 +162,16 @@ export class SetFixture { this.dai = await this._deployer.setV2.deployTokenMock(this._ownerAddress, ether(1000000), 18); this.usdt = await this._deployer.setV2.deployTokenMock(this._ownerAddress, ether(100000), 6); + this.component1Price = ether(230); + this.component2Price = ether(1); + this.component3Price = ether(9000); + this.component4Price = ether(1); + + this.ETH_USD_Oracle = await this._deployer.setV2.deployOracleMock(this.component1Price); + this.USD_USD_Oracle = await this._deployer.setV2.deployOracleMock(this.component2Price); + this.BTC_USD_Oracle = await this._deployer.setV2.deployOracleMock(this.component3Price); + this.DAI_USD_Oracle = await this._deployer.setV2.deployOracleMock(this.component4Price); + await this.weth.deposit({ value: ether(200000) }); await this.weth.approve(this.issuanceModule.address, ether(10000)); await this.usdc.approve(this.issuanceModule.address, ether(10000));