Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xd6aD7a6750A7593E092a9B218d66C0A814a3436e
Balance 0.120000 ETH
Nonce 1
Code Size 24188 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

24188 bytes
0x60806040526004361061025c5760003560e01c80637d7c2a1c11610144578063b6b55f25116100b6578063e849d6591161007a578063e849d659146108f1578063f5a41dea1461091a578063f69e204614610945578063f7c1ec7714610970578063f82ce27d1461099b578063fc0c546a146109c65761025c565b8063b6b55f251461080c578063cf8ca42614610835578063d9d7858a14610860578063db006a751461088b578063dd62ed3e146108b45761025c565b806399b71d5c1161010857806399b71d5c146106fa578063a160176d14610711578063a457c2d71461073c578063a728797114610779578063a9059cbb146107a4578063b69ef8a8146107e15761025c565b80637d7c2a1c146106395780638124955c14610650578063819faf7b146106795780638e4ec6ef146106a457806395d89b41146106cf5761025c565b80632e1a7d4d116101dd57806358782c21116101a157806358782c211461052757806361c1ec551461055257806365aab7491461057d57806370a08231146105a65780637137ef99146105e357806377c7b8fc1461060e5761025c565b80632e1a7d4d14610440578063313ce56714610469578063395093511461049457806339c0a7e1146104d157806357ded9c9146104fc5761025c565b80630eb2a267116102245780630eb2a2671461035957806316f0115b1461038457806318160ddd146103af57806323b872dd146103da5780632afcf480146104175761025c565b806306636c1c1461025e57806306a3fe591461029b57806306fdde03146102c6578063085d4883146102f1578063095ea7b31461031c575b005b34801561026a57600080fd5b5061028560048036036102809190810190614be6565b6109f1565b6040516102929190615a7b565b60405180910390f35b3480156102a757600080fd5b506102b0610c2f565b6040516102bd9190615624565b60405180910390f35b3480156102d257600080fd5b506102db610c55565b6040516102e891906157b0565b60405180910390f35b3480156102fd57600080fd5b50610306610cf7565b6040516103139190615795565b60405180910390f35b34801561032857600080fd5b50610343600480360361033e9190810190614ac9565b610d0a565b604051610350919061577a565b60405180910390f35b34801561036557600080fd5b5061036e610d28565b60405161037b9190615a7b565b60405180910390f35b34801561039057600080fd5b50610399610dda565b6040516103a69190615a7b565b60405180910390f35b3480156103bb57600080fd5b506103c4610de0565b6040516103d19190615a7b565b60405180910390f35b3480156103e657600080fd5b5061040160048036036103fc9190810190614a7a565b610dea565b60405161040e919061577a565b60405180910390f35b34801561042357600080fd5b5061043e60048036036104399190810190614be6565b610ec3565b005b34801561044c57600080fd5b5061046760048036036104629190810190614be6565b61102f565b005b34801561047557600080fd5b5061047e61143c565b60405161048b9190615a96565b60405180910390f35b3480156104a057600080fd5b506104bb60048036036104b69190810190614ac9565b611453565b6040516104c8919061577a565b60405180910390f35b3480156104dd57600080fd5b506104e6611506565b6040516104f39190615a7b565b60405180910390f35b34801561050857600080fd5b506105116115f6565b60405161051e9190615624565b60405180910390f35b34801561053357600080fd5b5061053c61161c565b6040516105499190615624565b60405180910390f35b34801561055e57600080fd5b50610567611642565b6040516105749190615a7b565b60405180910390f35b34801561058957600080fd5b506105a4600480360361059f9190810190614be6565b6116f4565b005b3480156105b257600080fd5b506105cd60048036036105c891908101906149ec565b611790565b6040516105da9190615a7b565b60405180910390f35b3480156105ef57600080fd5b506105f86117d8565b6040516106059190615a7b565b60405180910390f35b34801561061a57600080fd5b5061062361184b565b6040516106309190615a7b565b60405180910390f35b34801561064557600080fd5b5061064e61188d565b005b34801561065c57600080fd5b5061067760048036036106729190810190614be6565b6119d4565b005b34801561068557600080fd5b5061068e611ac8565b60405161069b9190615624565b60405180910390f35b3480156106b057600080fd5b506106b9611aee565b6040516106c69190615624565b60405180910390f35b3480156106db57600080fd5b506106e4611b14565b6040516106f191906157b0565b60405180910390f35b34801561070657600080fd5b5061070f611bb6565b005b34801561071d57600080fd5b50610726611dd9565b6040516107339190615795565b60405180910390f35b34801561074857600080fd5b50610763600480360361075e9190810190614ac9565b611f45565b604051610770919061577a565b60405180910390f35b34801561078557600080fd5b5061078e612012565b60405161079b9190615a7b565b60405180910390f35b3480156107b057600080fd5b506107cb60048036036107c69190810190614ac9565b6120fe565b6040516107d8919061577a565b60405180910390f35b3480156107ed57600080fd5b506107f661211c565b6040516108039190615a7b565b60405180910390f35b34801561081857600080fd5b50610833600480360361082e9190810190614be6565b6121ce565b005b34801561084157600080fd5b5061084a612332565b6040516108579190615a7b565b60405180910390f35b34801561086c57600080fd5b506108756123e4565b6040516108829190615a7b565b60405180910390f35b34801561089757600080fd5b506108b260048036036108ad9190810190614be6565b6123ea565b005b3480156108c057600080fd5b506108db60048036036108d69190810190614a3e565b612823565b6040516108e89190615a7b565b60405180910390f35b3480156108fd57600080fd5b5061091860048036036109139190810190614be6565b6128aa565b005b34801561092657600080fd5b5061092f61299c565b60405161093c9190615a7b565b60405180910390f35b34801561095157600080fd5b5061095a612a67565b6040516109679190615624565b60405180910390f35b34801561097c57600080fd5b50610985612a8d565b6040516109929190615624565b60405180910390f35b3480156109a757600080fd5b506109b0612b34565b6040516109bd9190615624565b60405180910390f35b3480156109d257600080fd5b506109db612bdb565b6040516109e89190615624565b60405180910390f35b600060606001604051908082528060200260200182016040528015610a3057816020015b610a1d614743565b815260200190600190039081610a155790505b50905060405180604001604052803073ffffffffffffffffffffffffffffffffffffffff168152602001600081525081600081518110610a6c57fe5b6020026020010181905250610a7f614773565b6040518060800160405280600115158152602001600080811115610a9f57fe5b8152602001600080811115610ab057fe5b8152602001858152509050610ac36147b1565b600081600001906001811115610ad557fe5b90816001811115610ae257fe5b815250506000816020018181525050818160400181905250600e54816060018181525050308160a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060606001604051908082528060200260200182016040528015610b7b57816020015b610b6861481d565b815260200190600190039081610b605790505b5090508181600081518110610b8c57fe5b6020026020010181905250600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a67a6a4585836040518363ffffffff1660e01b8152600401610bf4929190615743565b600060405180830381600087803b158015610c0e57600080fd5b505af1158015610c22573d6000803e3d6000fd5b5050505050505050919050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606060038054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ced5780601f10610cc257610100808354040283529160200191610ced565b820191906000526020600020905b815481529060010190602001808311610cd057829003601f168201915b5050505050905090565b600f60149054906101000a900460ff1681565b6000610d1e610d17612c01565b8484612c09565b6001905092915050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d85919061563f565b60206040518083038186803b158015610d9d57600080fd5b505afa158015610db1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610dd59190810190614c0f565b905090565b60075481565b6000600254905090565b6000610df7848484612dd4565b610eb884610e03612c01565b610eb385604051806060016040528060288152602001615ded60289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610e69612c01565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461305e9092919063ffffffff16565b612c09565b600190509392505050565b60016006600082825401925050819055506000600654905060008211610f1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f1590615972565b60405180910390fd5b610f266117d8565b600781905550610f7b333084600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166130b9909392919063ffffffff16565b610f8361188d565b600080905060006007541415610fa25782905082600781905550610fce565b610fcb600754610fbd6002548661315b90919063ffffffff16565b6131cb90919063ffffffff16565b90505b610fd66117d8565b600781905550610fe63382613215565b50600654811461102b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611022906159d2565b60405180910390fd5b5050565b6001600660008282540192505081905550600060065490506000821161108a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611081906158f2565b60405180910390fd5b600061109533611790565b9050808311156110da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d1906158d2565b60405180910390fd5b6110e261339d565b60078190555060006111136002546111058660075461315b90919063ffffffff16565b6131cb90919063ffffffff16565b905061119d846040518060400160405280601d81526020017f72656465656d20616d6f756e7420657863656564732062616c616e63650000008152506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461305e9092919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506111f48460025461341090919063ffffffff16565b600281905550600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040516112589190615a7b565b60405180910390a36000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016112bd919061563f565b60206040518083038186803b1580156112d557600080fd5b505afa1580156112e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061130d9190810190614c0f565b9050818110156113335761133261132d828461341090919063ffffffff16565b61345a565b5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b815260040161139092919061565a565b602060405180830381600087803b1580156113aa57600080fd5b505af11580156113be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113e29190810190614b05565b506113eb61339d565b6007819055505050506006548114611438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142f906159d2565b60405180910390fd5b5050565b6000600560009054906101000a900460ff16905090565b60006114fc611460612c01565b846114f78560016000611471612c01565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135d090919063ffffffff16565b612c09565b6001905092915050565b6000611510614889565b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c190c2ec60405180604001604052803073ffffffffffffffffffffffffffffffffffffffff1681526020016000815250600e546040518363ffffffff1660e01b815260040161159a929190615a52565b604080518083038186803b1580156115b157600080fd5b505afa1580156115c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115e99190810190614bbd565b9050806020015191505090565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161169f919061563f565b60206040518083038186803b1580156116b757600080fd5b505afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116ef9190810190614c0f565b905090565b6116fc612a8d565b73ffffffffffffffffffffffffffffffffffffffff1663d2d0e066600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168360006040518463ffffffff1660e01b815260040161175b9392919061570c565b600060405180830381600087803b15801561177557600080fd5b505af1158015611789573d6000803e3d6000fd5b5050505050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006118466117e561211c565b6118386117f0612332565b61182a6117fb611506565b61181c61180661299c565b61180e612012565b6135d090919063ffffffff16565b6135d090919063ffffffff16565b6135d090919063ffffffff16565b6135d090919063ffffffff16565b905090565b6000806118566117d8565b9050611887600254611879670de0b6b3a76400008461315b90919063ffffffff16565b6131cb90919063ffffffff16565b91505090565b6000611897611dd9565b9050600f60149054906101000a900460ff1660048111156118b457fe5b8160048111156118c057fe5b146118ce576118cd613625565b5b60006118d861211c565b11156119ae57600160048111156118eb57fe5b8160048111156118f757fe5b14156119135761190d61190861211c565b6109f1565b506119ad565b60048081111561191f57fe5b81600481111561192b57fe5b14156119465761194161193c61211c565b6119d4565b6119ac565b6002600481111561195357fe5b81600481111561195f57fe5b141561197a5761197561197061211c565b6128aa565b6119ab565b6003600481111561198757fe5b81600481111561199357fe5b14156119aa576119a96119a461211c565b6116f4565b5b5b5b5b5b80600f60146101000a81548160ff021916908360048111156119cc57fe5b021790555050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f1930846040518363ffffffff1660e01b8152600401611a3392919061565a565b602060405180830381600087803b158015611a4d57600080fd5b505af1158015611a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611a859190810190614c0f565b11611ac5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611abc90615992565b60405180910390fd5b50565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606060048054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611bac5780601f10611b8157610100808354040283529160200191611bac565b820191906000526020600020905b815481529060010190602001808311611b8f57829003601f168201915b5050505050905090565b611c45600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661369e9092919063ffffffff16565b611cd4600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661369e9092919063ffffffff16565b611d48611cdf612b34565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661369e9092919063ffffffff16565b611dd7600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661369e9092919063ffffffff16565b565b6000806000806000600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d88be3c0600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401611e5e9190615624565b60006040518083038186803b158015611e7657600080fd5b505afa158015611e8a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250611eb39190810190614b2e565b945094509450945050600080905080851115611ecd578490505b80841115611ed9578390505b80831115611ee5578290505b80821115611ef1578190505b600080905085821415611f075760029050611f39565b84821415611f185760049050611f38565b83821415611f295760039050611f37565b82821415611f3657600190505b5b5b5b80965050505050505090565b6000612008611f52612c01565b8461200385604051806060016040528060258152602001615e156025913960016000611f7c612c01565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461305e9092919063ffffffff16565b612c09565b6001905092915050565b60008061201d611642565b905060008111156120f7576120f4670de0b6b3a76400006120e6600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561209f57600080fd5b505afa1580156120b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506120d79190810190614c0f565b8461315b90919063ffffffff16565b6131cb90919063ffffffff16565b90505b8091505090565b600061211261210b612c01565b8484612dd4565b6001905092915050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401612179919061563f565b60206040518083038186803b15801561219157600080fd5b505afa1580156121a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506121c99190810190614c0f565b905090565b60016006600082825401925050819055506000600654905060008211612229576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161222090615972565b60405180910390fd5b61223161339d565b600781905550612286333084600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166130b9909392919063ffffffff16565b6000809050600060075414156122a557829050826007819055506122d1565b6122ce6007546122c06002548661315b90919063ffffffff16565b6131cb90919063ffffffff16565b90505b6122d961339d565b6007819055506122e93382613215565b50600654811461232e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612325906159d2565b60405180910390fd5b5050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161238f919061563f565b60206040518083038186803b1580156123a757600080fd5b505afa1580156123bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123df9190810190614c0f565b905090565b600e5481565b60016006600082825401925050819055506000600654905060008211612445576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161243c906158f2565b60405180910390fd5b600061245033611790565b905080831115612495576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248c906158d2565b60405180910390fd5b61249d6117d8565b60078190555060006124ce6002546124c08660075461315b90919063ffffffff16565b6131cb90919063ffffffff16565b9050612558846040518060400160405280601d81526020017f72656465656d20616d6f756e7420657863656564732062616c616e63650000008152506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461305e9092919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506125af8460025461341090919063ffffffff16565b600281905550600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040516126139190615a7b565b60405180910390a36000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401612678919061563f565b60206040518083038186803b15801561269057600080fd5b505afa1580156126a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506126c89190810190614c0f565b90506000600f60149054906101000a900460ff16905082821015612746576126ee611dd9565b9050600f60149054906101000a900460ff16600481111561270b57fe5b81600481111561271757fe5b1461272957612724613625565b612745565b61274461273f838561341090919063ffffffff16565b61345a565b5b5b6127933384600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166138159092919063ffffffff16565b600f60149054906101000a900460ff1660048111156127ae57fe5b8160048111156127ba57fe5b146127c9576127c8816138b4565b5b6127d16117d8565b60078190555050505050600654811461281f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612816906159d2565b60405180910390fd5b5050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a0712d68836040518263ffffffff1660e01b81526004016129079190615a7b565b602060405180830381600087803b15801561292157600080fd5b505af1158015612935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506129599190810190614c0f565b14612999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299090615832565b60405180910390fd5b50565b6000806129a7610d28565b90506000811115612a6057600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306b3efd6306040518263ffffffff1660e01b8152600401612a0d919061563f565b60206040518083038186803b158015612a2557600080fd5b505afa158015612a39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a5d9190810190614c0f565b90505b8091505090565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612af757600080fd5b505afa158015612b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612b2f9190810190614a15565b905090565b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6ff7606040518163ffffffff1660e01b815260040160206040518083038186803b158015612b9e57600080fd5b505afa158015612bb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612bd69190810190614a15565b905090565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7090615952565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612ce9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ce090615812565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051612dc79190615a7b565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612e44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e3b90615912565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612eb4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eab906157d2565b60405180910390fd5b612f1f81604051806060016040528060268152602001615dc7602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461305e9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612fb2816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135d090919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516130519190615a7b565b60405180910390a3505050565b60008383111582906130a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161309d91906157b0565b60405180910390fd5b5060008385039050809150509392505050565b613155848573ffffffffffffffffffffffffffffffffffffffff166323b872dd905060e01b8585856040516024016130f3939291906156ac565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506139ba565b50505050565b60008083141561316e57600090506131c5565b600082840290508284828161317f57fe5b04146131c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131b790615892565b60405180910390fd5b809150505b92915050565b600061320d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613b2c565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613285576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161327c90615a32565b60405180910390fd5b61329a816002546135d090919063ffffffff16565b6002819055506132f1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546135d090919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516133919190615a7b565b60405180910390a35050565b600061340b6133aa613b8d565b6133fd6133b5613c3f565b6133ef6133c0613cf1565b6133e16133cb613de1565b6133d3613eac565b6135d090919063ffffffff16565b6135d090919063ffffffff16565b6135d090919063ffffffff16565b6135d090919063ffffffff16565b905090565b600061345283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061305e565b905092915050565b6002600481111561346757fe5b600f60149054906101000a900460ff16600481111561348257fe5b14156134925761349181613f98565b5b6003600481111561349f57fe5b600f60149054906101000a900460ff1660048111156134ba57fe5b141561351457806134c9612332565b101561350a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161350190615932565b60405180910390fd5b6135138161403e565b5b6001600481111561352157fe5b600f60149054906101000a900460ff16600481111561353c57fe5b1415613596578061354b611506565b101561358c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161358390615932565b60405180910390fd5b613595816140ce565b5b6004808111156135a257fe5b600f60149054906101000a900460ff1660048111156135bd57fe5b14156135cd576135cc81614308565b5b50565b60008082840190508381101561361b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161361290615852565b60405180910390fd5b8091505092915050565b600061362f6143ae565b905060008111156136445761364381614460565b5b61364c613cf1565b9050600081111561366157613660816140ce565b5b613669614552565b9050600081111561367e5761367d81614604565b5b613686613c3f565b9050600081111561369b5761369a8161403e565b5b50565b6000811480613737575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b81526004016136e5929190615683565b60206040518083038186803b1580156136fd57600080fd5b505afa158015613711573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506137359190810190614c0f565b145b613776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161376d906159f2565b60405180910390fd5b613810838473ffffffffffffffffffffffffffffffffffffffff1663095ea7b3905060e01b84846040516024016137ae9291906156e3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506139ba565b505050565b6138af838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb905060e01b848460405160240161384d9291906156e3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506139ba565b505050565b60006138be613b8d565b111561399457600160048111156138d157fe5b8160048111156138dd57fe5b14156138f9576138f36138ee613b8d565b6109f1565b50613993565b60048081111561390557fe5b81600481111561391157fe5b141561392c57613927613922613b8d565b6119d4565b613992565b6002600481111561393957fe5b81600481111561394557fe5b14156139605761395b613956613b8d565b6128aa565b613991565b6003600481111561396d57fe5b81600481111561397957fe5b14156139905761398f61398a613b8d565b6116f4565b5b5b5b5b5b80600f60146101000a81548160ff021916908360048111156139b257fe5b021790555050565b6139d98273ffffffffffffffffffffffffffffffffffffffff166146f8565b613a18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a0f90615a12565b60405180910390fd5b600060608373ffffffffffffffffffffffffffffffffffffffff1683604051613a41919061560d565b6000604051808303816000865af19150503d8060008114613a7e576040519150601f19603f3d011682016040523d82523d6000602084013e613a83565b606091505b509150915081613ac8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613abf90615872565b60405180910390fd5b600081511115613b265780806020019051613ae69190810190614b05565b613b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b1c906159b2565b60405180910390fd5b5b50505050565b60008083118290613b73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b6a91906157b0565b60405180910390fd5b506000838581613b7f57fe5b049050809150509392505050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401613bea919061563f565b60206040518083038186803b158015613c0257600080fd5b505afa158015613c16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613c3a9190810190614c0f565b905090565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401613c9c919061563f565b60206040518083038186803b158015613cb457600080fd5b505afa158015613cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613cec9190810190614c0f565b905090565b6000613cfb614889565b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c190c2ec60405180604001604052803073ffffffffffffffffffffffffffffffffffffffff1681526020016000815250600e546040518363ffffffff1660e01b8152600401613d85929190615a52565b604080518083038186803b158015613d9c57600080fd5b505afa158015613db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613dd49190810190614bbd565b9050806020015191505090565b600080613dec610d28565b90506000811115613ea557600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306b3efd6306040518263ffffffff1660e01b8152600401613e52919061563f565b60206040518083038186803b158015613e6a57600080fd5b505afa158015613e7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613ea29190810190614c0f565b90505b8091505090565b600080613eb7611642565b90506000811115613f9157613f8e670de0b6b3a7640000613f80600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015613f3957600080fd5b505afa158015613f4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613f719190810190614c0f565b8461315b90919063ffffffff16565b6131cb90919063ffffffff16565b90505b8091505090565b6000613fa2611642565b90506000613fae612012565b905082811015613ff3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613fea90615932565b60405180910390fd5b600061402d600161401f84614011888861315b90919063ffffffff16565b6131cb90919063ffffffff16565b6135d090919063ffffffff16565b905061403881614460565b50505050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663db006a75826040518263ffffffff1660e01b81526004016140999190615a7b565b600060405180830381600087803b1580156140b357600080fd5b505af11580156140c7573d6000803e3d6000fd5b5050505050565b6060600160405190808252806020026020018201604052801561410b57816020015b6140f8614743565b8152602001906001900390816140f05790505b50905060405180604001604052803073ffffffffffffffffffffffffffffffffffffffff16815260200160008152508160008151811061414757fe5b602002602001018190525061415a614773565b604051806080016040528060001515815260200160008081111561417a57fe5b815260200160008081111561418b57fe5b815260200184815250905061419e6147b1565b6001816000019060018111156141b057fe5b908160018111156141bd57fe5b815250506000816020018181525050818160400181905250600e54816060018181525050308160a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506060600160405190808252806020026020018201604052801561425657816020015b61424361481d565b81526020019060019003908161423b5790505b509050818160008151811061426757fe5b6020026020010181905250600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a67a6a4585836040518363ffffffff1660e01b81526004016142cf929190615743565b600060405180830381600087803b1580156142e957600080fd5b505af11580156142fd573d6000803e3d6000fd5b505050505050505050565b6000614312610d28565b9050600061431e61299c565b905082811015614363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161435a90615932565b60405180910390fd5b600061439d600161438f84614381888861315b90919063ffffffff16565b6131cb90919063ffffffff16565b6135d090919063ffffffff16565b90506143a881614604565b50505050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161440b919061563f565b60206040518083038186803b15801561442357600080fd5b505afa158015614437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061445b9190810190614c0f565b905090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663db006a75836040518263ffffffff1660e01b81526004016144bd9190615a7b565b602060405180830381600087803b1580156144d757600080fd5b505af11580156144eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061450f9190810190614c0f565b1461454f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614546906157f2565b60405180910390fd5b50565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016145af919061563f565b60206040518083038186803b1580156145c757600080fd5b505afa1580156145db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506145ff9190810190614c0f565b905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac30846040518363ffffffff1660e01b815260040161466392919061565a565b602060405180830381600087803b15801561467d57600080fd5b505af1158015614691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506146b59190810190614c0f565b116146f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016146ec906158b2565b60405180910390fd5b50565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f91506000801b821415801561473a5750808214155b92505050919050565b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b604051806080016040528060001515815260200160008081111561479357fe5b81526020016000808111156147a457fe5b8152602001600081525090565b604051806101000160405280600060018111156147ca57fe5b8152602001600081526020016147de6148a5565b81526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001606081525090565b6040518061010001604052806000600181111561483657fe5b81526020016000815260200161484a6148a5565b81526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001606081525090565b6040518060400160405280600015158152602001600081525090565b60405180608001604052806000151581526020016000808111156148c557fe5b81526020016000808111156148d657fe5b8152602001600081525090565b6000813590506148f281615d81565b92915050565b60008151905061490781615d81565b92915050565b60008151905061491c81615d98565b92915050565b600082601f83011261493357600080fd5b815161494661494182615ade565b615ab1565b9150808252602083016020830185838301111561496257600080fd5b61496d838284615d09565b50505092915050565b60006040828403121561498857600080fd5b6149926040615ab1565b905060006149a28482850161490d565b60008301525060206149b6848285016149d7565b60208301525092915050565b6000813590506149d181615daf565b92915050565b6000815190506149e681615daf565b92915050565b6000602082840312156149fe57600080fd5b6000614a0c848285016148e3565b91505092915050565b600060208284031215614a2757600080fd5b6000614a35848285016148f8565b91505092915050565b60008060408385031215614a5157600080fd5b6000614a5f858286016148e3565b9250506020614a70858286016148e3565b9150509250929050565b600080600060608486031215614a8f57600080fd5b6000614a9d868287016148e3565b9350506020614aae868287016148e3565b9250506040614abf868287016149c2565b9150509250925092565b60008060408385031215614adc57600080fd5b6000614aea858286016148e3565b9250506020614afb858286016149c2565b9150509250929050565b600060208284031215614b1757600080fd5b6000614b258482850161490d565b91505092915050565b600080600080600060a08688031215614b4657600080fd5b600086015167ffffffffffffffff811115614b6057600080fd5b614b6c88828901614922565b9550506020614b7d888289016149d7565b9450506040614b8e888289016149d7565b9350506060614b9f888289016149d7565b9250506080614bb0888289016149d7565b9150509295509295909350565b600060408284031215614bcf57600080fd5b6000614bdd84828501614976565b91505092915050565b600060208284031215614bf857600080fd5b6000614c06848285016149c2565b91505092915050565b600060208284031215614c2157600080fd5b6000614c2f848285016149d7565b91505092915050565b6000614c44838361547a565b905092915050565b6000614c588383615582565b60408301905092915050565b614c6d81615c79565b82525050565b614c7c81615bca565b82525050565b614c8b81615bca565b82525050565b6000614c9c82615b2a565b614ca68185615b7b565b935083602082028501614cb885615b0a565b8060005b85811015614cf45784840389528151614cd58582614c38565b9450614ce083615b61565b925060208a01995050600181019050614cbc565b50829750879550505050505092915050565b6000614d1182615b35565b614d1b8185615b8c565b9350614d2683615b1a565b8060005b83811015614d57578151614d3e8882614c4c565b9750614d4983615b6e565b925050600181019050614d2a565b5085935050505092915050565b614d6d81615bdc565b82525050565b614d7c81615bdc565b82525050565b6000614d8d82615b4b565b614d978185615bae565b9350614da7818560208601615d09565b80840191505092915050565b6000614dbe82615b40565b614dc88185615b9d565b9350614dd8818560208601615d09565b614de181615d3c565b840191505092915050565b614df581615c8b565b82525050565b614e0481615c9d565b82525050565b614e1381615caf565b82525050565b614e2281615cc1565b82525050565b614e3181615cd3565b82525050565b6000614e4282615b56565b614e4c8185615bb9565b9350614e5c818560208601615d09565b614e6581615d3c565b840191505092915050565b6000614e7d602383615bb9565b91507f45524332303a207472616e7366657220746f20746865207a65726f206164647260008301527f65737300000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614ee3601983615bb9565b91507f434f4d504f554e443a207769746864726177206661696c6564000000000000006000830152602082019050919050565b6000614f23602283615bb9565b91507f45524332303a20617070726f766520746f20746865207a65726f20616464726560008301527f73730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614f89601783615bb9565b91507f434f4d504f554e443a20737570706c79206661696c65640000000000000000006000830152602082019050919050565b6000614fc9601b83615bb9565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000615009602083615bb9565b91507f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646000830152602082019050919050565b6000615049602183615bb9565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006150af601883615bb9565b91507f46554c4352554d3a207769746864726177206661696c656400000000000000006000830152602082019050919050565b60006150ef601483615bb9565b91507f696e73756666696369656e742062616c616e63650000000000000000000000006000830152602082019050919050565b600061512f601f83615bb9565b91507f7769746864726177206d7573742062652067726561746572207468616e2030006000830152602082019050919050565b600061516f602583615bb9565b91507f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008301527f64726573730000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006151d5601283615bb9565b91507f696e73756666696369656e742066756e647300000000000000000000000000006000830152602082019050919050565b6000615215602483615bb9565b91507f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008301527f72657373000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061527b601e83615bb9565b91507f6465706f736974206d7573742062652067726561746572207468616e203000006000830152602082019050919050565b60006152bb601683615bb9565b91507f46554c4352554d3a20737570706c79206661696c6564000000000000000000006000830152602082019050919050565b60006152fb602a83615bb9565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000615361601f83615bb9565b91507f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006000830152602082019050919050565b60006153a1603683615bb9565b91507f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60008301527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006020830152604082019050919050565b6000615407601f83615bb9565b91507f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e7472616374006000830152602082019050919050565b6000615447601f83615bb9565b91507f45524332303a206d696e7420746f20746865207a65726f2061646472657373006000830152602082019050919050565b6000610160830160008301516154936000860182614dec565b5060208301516154a660208601826155e0565b5060408301516154b9604086018261552d565b5060608301516154cc60c08601826155e0565b5060808301516154df60e08601826155e0565b5060a08301516154f3610100860182614c73565b5060c08301516155076101208601826155e0565b5060e08301518482036101408601526155208282614db3565b9150508091505092915050565b6080820160008201516155436000850182614d64565b5060208201516155566020850182614dfb565b5060408201516155696040850182614e0a565b50606082015161557c60608501826155e0565b50505050565b6040820160008201516155986000850182614c73565b5060208201516155ab60208501826155e0565b50505050565b6040820160008201516155c76000850182614c73565b5060208201516155da60208501826155e0565b50505050565b6155e981615c62565b82525050565b6155f881615c62565b82525050565b61560781615c6c565b82525050565b60006156198284614d82565b915081905092915050565b60006020820190506156396000830184614c82565b92915050565b60006020820190506156546000830184614c64565b92915050565b600060408201905061566f6000830185614c64565b61567c60208301846155ef565b9392505050565b60006040820190506156986000830185614c82565b6156a56020830184614c82565b9392505050565b60006060820190506156c16000830186614c82565b6156ce6020830185614c82565b6156db60408301846155ef565b949350505050565b60006040820190506156f86000830185614c82565b61570560208301846155ef565b9392505050565b60006060820190506157216000830186614c82565b61572e60208301856155ef565b61573b6040830184614e28565b949350505050565b6000604082019050818103600083015261575d8185614d06565b905081810360208301526157718184614c91565b90509392505050565b600060208201905061578f6000830184614d73565b92915050565b60006020820190506157aa6000830184614e19565b92915050565b600060208201905081810360008301526157ca8184614e37565b905092915050565b600060208201905081810360008301526157eb81614e70565b9050919050565b6000602082019050818103600083015261580b81614ed6565b9050919050565b6000602082019050818103600083015261582b81614f16565b9050919050565b6000602082019050818103600083015261584b81614f7c565b9050919050565b6000602082019050818103600083015261586b81614fbc565b9050919050565b6000602082019050818103600083015261588b81614ffc565b9050919050565b600060208201905081810360008301526158ab8161503c565b9050919050565b600060208201905081810360008301526158cb816150a2565b9050919050565b600060208201905081810360008301526158eb816150e2565b9050919050565b6000602082019050818103600083015261590b81615122565b9050919050565b6000602082019050818103600083015261592b81615162565b9050919050565b6000602082019050818103600083015261594b816151c8565b9050919050565b6000602082019050818103600083015261596b81615208565b9050919050565b6000602082019050818103600083015261598b8161526e565b9050919050565b600060208201905081810360008301526159ab816152ae565b9050919050565b600060208201905081810360008301526159cb816152ee565b9050919050565b600060208201905081810360008301526159eb81615354565b9050919050565b60006020820190508181036000830152615a0b81615394565b9050919050565b60006020820190508181036000830152615a2b816153fa565b9050919050565b60006020820190508181036000830152615a4b8161543a565b9050919050565b6000606082019050615a6760008301856155b1565b615a7460408301846155ef565b9392505050565b6000602082019050615a9060008301846155ef565b92915050565b6000602082019050615aab60008301846155fe565b92915050565b6000604051905081810181811067ffffffffffffffff82111715615ad457600080fd5b8060405250919050565b600067ffffffffffffffff821115615af557600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000615bd582615c42565b9050919050565b60008115159050919050565b6000819050615bf682615d4d565b919050565b6000819050615c0982615d5a565b919050565b6000819050615c1c82615d67565b919050565b6000819050615c2f82615d74565b919050565b600061ffff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000615c8482615ce5565b9050919050565b6000615c9682615be8565b9050919050565b6000615ca882615bfb565b9050919050565b6000615cba82615c0e565b9050919050565b6000615ccc82615c21565b9050919050565b6000615cde82615c34565b9050919050565b6000615cf082615cf7565b9050919050565b6000615d0282615c42565b9050919050565b60005b83811015615d27578082015181840152602081019050615d0c565b83811115615d36576000848401525b50505050565b6000601f19601f8301169050919050565b60028110615d5757fe5b50565b60018110615d6457fe5b50565b60018110615d7157fe5b50565b60058110615d7e57fe5b50565b615d8a81615bca565b8114615d9557600080fd5b50565b615da181615bdc565b8114615dac57600080fd5b50565b615db881615c62565b8114615dc357600080fd5b5056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa365627a7a7231582031f1273c5c715e345ef2ed711e46568bd407c17fe3d2fc164ef9944ea5d4c9976c6578706572696d656e74616cf564736f6c634300050c0040

Verified Source Code Partial Match

Compiler: v0.5.12+commit.7709ece9 EVM: petersburg Optimization: No
yUSDC.sol 773 lines
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

contract Context {
    constructor () internal { }
    // solhint-disable-previous-line no-empty-blocks

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 _totalSupply;
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }
    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }
    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }
    function _approve(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
    }
}

contract ERC20Detailed is IERC20 {
    string private _name;
    string private _symbol;
    uint8 private _decimals;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;
    }
    function name() public view returns (string memory) {
        return _name;
    }
    function symbol() public view returns (string memory) {
        return _symbol;
    }
    function decimals() public view returns (uint8) {
        return _decimals;
    }
}

contract ReentrancyGuard {
    uint256 private _guardCounter;

    constructor () internal {
        _guardCounter = 1;
    }

    modifier nonReentrant() {
        _guardCounter += 1;
        uint256 localCounter = _guardCounter;
        _;
        require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
    }
}

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;

        return c;
    }
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

library Address {
    function isContract(address account) internal view returns (bool) {
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != 0x0 && codehash != accountHash);
    }
    function toPayable(address account) internal pure returns (address payable) {
        return address(uint160(account));
    }
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-call-value
        (bool success, ) = recipient.call.value(amount)("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }
}

library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

interface Compound {
    function mint ( uint256 mintAmount ) external returns ( uint256 );
    function redeem(uint256 redeemTokens) external returns (uint256);
    function exchangeRateStored() external view returns (uint);
}

interface Fulcrum {
    function mint(address receiver, uint256 amount) external payable returns (uint256 mintAmount);
    function burn(address receiver, uint256 burnAmount) external returns (uint256 loanAmountPaid);
    function assetBalanceOf(address _owner) external view returns (uint256 balance);
}

interface ILendingPoolAddressesProvider {
    function getLendingPool() external view returns (address);
}

interface Aave {
    function deposit(address _reserve, uint256 _amount, uint16 _referralCode) external;
}

interface AToken {
    function redeem(uint256 amount) external;
}

interface IIEarnManager {
    function recommend(address _token) external view returns (
      string memory choice,
      uint256 capr,
      uint256 iapr,
      uint256 aapr,
      uint256 dapr
    );
}

contract Structs {
    struct Val {
        uint256 value;
    }

    enum ActionType {
        Deposit,   // supply tokens
        Withdraw  // borrow tokens
    }

    enum AssetDenomination {
        Wei // the amount is denominated in wei
    }

    enum AssetReference {
        Delta // the amount is given as a delta from the current value
    }

    struct AssetAmount {
        bool sign; // true if positive
        AssetDenomination denomination;
        AssetReference ref;
        uint256 value;
    }

    struct ActionArgs {
        ActionType actionType;
        uint256 accountId;
        AssetAmount amount;
        uint256 primaryMarketId;
        uint256 secondaryMarketId;
        address otherAddress;
        uint256 otherAccountId;
        bytes data;
    }

    struct Info {
        address owner;  // The address that owns the account
        uint256 number; // A nonce that allows a single address to control many accounts
    }

    struct Wei {
        bool sign; // true if positive
        uint256 value;
    }
}

contract DyDx is Structs {
    function getAccountWei(Info memory account, uint256 marketId) public view returns (Wei memory);
    function operate(Info[] memory, ActionArgs[] memory) public;
}

interface LendingPoolAddressesProvider {
    function getLendingPool() external view returns (address);
    function getLendingPoolCore() external view returns (address);
}

contract yUSDC is ERC20, ERC20Detailed, ReentrancyGuard, Structs {
  using SafeERC20 for IERC20;
  using Address for address;
  using SafeMath for uint256;

  uint256 public pool;
  address public token;
  address public compound;
  address public fulcrum;
  address public aave;
  address public aaveToken;
  address public dydx;
  uint256 public dToken;
  address public apr;

  enum Lender {
      NONE,
      DYDX,
      COMPOUND,
      AAVE,
      FULCRUM
  }

  Lender public provider = Lender.NONE;

  constructor () public ERC20Detailed("iearn USDC", "yUSDC", 6) {
    token = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
    apr = address(0xdD6d648C991f7d47454354f4Ef326b04025a48A8);
    dydx = address(0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e);
    aave = address(0x24a42fD28C976A61Df5D00D0599C34c4f90748c8);
    fulcrum = address(0xF013406A0B1d544238083DF0B93ad0d2cBE0f65f);
    aaveToken = address(0x9bA00D6856a4eDF4665BcA2C2309936572473B7E);
    compound = address(0x39AA39c021dfbaE8faC545936693aC917d5E7563);
    dToken = 2;
    approveToken();
  }

  // Quick swap low gas method for pool swaps
  function deposit(uint256 _amount)
      external
      nonReentrant
  {
      require(_amount > 0, "deposit must be greater than 0");
      pool = _calcPoolValueInToken();

      IERC20(token).safeTransferFrom(msg.sender, address(this), _amount);

      // Calculate pool shares
      uint256 shares = 0;
      if (pool == 0) {
        shares = _amount;
        pool = _amount;
      } else {
        shares = (_amount.mul(_totalSupply)).div(pool);
      }
      pool = _calcPoolValueInToken();
      _mint(msg.sender, shares);
  }

  // No rebalance implementation for lower fees and faster swaps
  function withdraw(uint256 _shares)
      external
      nonReentrant
  {
      require(_shares > 0, "withdraw must be greater than 0");

      uint256 ibalance = balanceOf(msg.sender);
      require(_shares <= ibalance, "insufficient balance");

      // Could have over value from cTokens
      pool = _calcPoolValueInToken();
      // Calc to redeem before updating balances
      uint256 r = (pool.mul(_shares)).div(_totalSupply);


      _balances[msg.sender] = _balances[msg.sender].sub(_shares, "redeem amount exceeds balance");
      _totalSupply = _totalSupply.sub(_shares);

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

      // Check balance
      uint256 b = IERC20(token).balanceOf(address(this));
      if (b < r) {
        _withdrawSome(r.sub(b));
      }

      IERC20(token).transfer(msg.sender, r);
      pool = _calcPoolValueInToken();
  }

  function() external payable {

  }

  function recommend() public view returns (Lender) {
    (,uint256 capr,uint256 iapr,uint256 aapr,uint256 dapr) = IIEarnManager(apr).recommend(token);
    uint256 max = 0;
    if (capr > max) {
      max = capr;
    }
    if (iapr > max) {
      max = iapr;
    }
    if (aapr > max) {
      max = aapr;
    }
    if (dapr > max) {
      max = dapr;
    }

    Lender newProvider = Lender.NONE;
    if (max == capr) {
      newProvider = Lender.COMPOUND;
    } else if (max == iapr) {
      newProvider = Lender.FULCRUM;
    } else if (max == aapr) {
      newProvider = Lender.AAVE;
    } else if (max == dapr) {
      newProvider = Lender.DYDX;
    }
    return newProvider;
  }

  function supplyDydx(uint256 amount) public returns(uint) {
      Info[] memory infos = new Info[](1);
      infos[0] = Info(address(this), 0);

      AssetAmount memory amt = AssetAmount(true, AssetDenomination.Wei, AssetReference.Delta, amount);
      ActionArgs memory act;
      act.actionType = ActionType.Deposit;
      act.accountId = 0;
      act.amount = amt;
      act.primaryMarketId = dToken;
      act.otherAddress = address(this);

      ActionArgs[] memory args = new ActionArgs[](1);
      args[0] = act;

      DyDx(dydx).operate(infos, args);
  }

  function _withdrawDydx(uint256 amount) internal {
      Info[] memory infos = new Info[](1);
      infos[0] = Info(address(this), 0);

      AssetAmount memory amt = AssetAmount(false, AssetDenomination.Wei, AssetReference.Delta, amount);
      ActionArgs memory act;
      act.actionType = ActionType.Withdraw;
      act.accountId = 0;
      act.amount = amt;
      act.primaryMarketId = dToken;
      act.otherAddress = address(this);

      ActionArgs[] memory args = new ActionArgs[](1);
      args[0] = act;

      DyDx(dydx).operate(infos, args);
  }

  function getAave() public view returns (address) {
    return LendingPoolAddressesProvider(aave).getLendingPool();
  }
  function getAaveCore() public view returns (address) {
    return LendingPoolAddressesProvider(aave).getLendingPoolCore();
  }

  function approveToken() public {
      IERC20(token).safeApprove(compound, uint(-1)); //also add to constructor
      IERC20(token).safeApprove(dydx, uint(-1));
      IERC20(token).safeApprove(getAaveCore(), uint(-1));
      IERC20(token).safeApprove(fulcrum, uint(-1));
  }

  function balance() public view returns (uint256) {
    return IERC20(token).balanceOf(address(this));
  }

  function balanceDydx() public view returns (uint256) {
      Wei memory bal = DyDx(dydx).getAccountWei(Info(address(this), 0), dToken);
      return bal.value;
  }
  function balanceCompound() public view returns (uint256) {
      return IERC20(compound).balanceOf(address(this));
  }
  function balanceCompoundInToken() public view returns (uint256) {
    // Mantisa 1e18 to decimals
    uint256 b = balanceCompound();
    if (b > 0) {
      b = b.mul(Compound(compound).exchangeRateStored()).div(1e18);
    }
    return b;
  }
  function balanceFulcrumInToken() public view returns (uint256) {
    uint256 b = balanceFulcrum();
    if (b > 0) {
      b = Fulcrum(fulcrum).assetBalanceOf(address(this));
    }
    return b;
  }
  function balanceFulcrum() public view returns (uint256) {
    return IERC20(fulcrum).balanceOf(address(this));
  }
  function balanceAave() public view returns (uint256) {
    return IERC20(aaveToken).balanceOf(address(this));
  }

  function _balance() internal view returns (uint256) {
    return IERC20(token).balanceOf(address(this));
  }

  function _balanceDydx() internal view returns (uint256) {
      Wei memory bal = DyDx(dydx).getAccountWei(Info(address(this), 0), dToken);
      return bal.value;
  }
  function _balanceCompound() internal view returns (uint256) {
      return IERC20(compound).balanceOf(address(this));
  }
  function _balanceCompoundInToken() internal view returns (uint256) {
    // Mantisa 1e18 to decimals
    uint256 b = balanceCompound();
    if (b > 0) {
      b = b.mul(Compound(compound).exchangeRateStored()).div(1e18);
    }
    return b;
  }
  function _balanceFulcrumInToken() internal view returns (uint256) {
    uint256 b = balanceFulcrum();
    if (b > 0) {
      b = Fulcrum(fulcrum).assetBalanceOf(address(this));
    }
    return b;
  }
  function _balanceFulcrum() internal view returns (uint256) {
    return IERC20(fulcrum).balanceOf(address(this));
  }
  function _balanceAave() internal view returns (uint256) {
    return IERC20(aaveToken).balanceOf(address(this));
  }

  function _withdrawAll() internal {
    uint256 amount = _balanceCompound();
    if (amount > 0) {
      _withdrawCompound(amount);
    }
    amount = _balanceDydx();
    if (amount > 0) {
      _withdrawDydx(amount);
    }
    amount = _balanceFulcrum();
    if (amount > 0) {
      _withdrawFulcrum(amount);
    }
    amount = _balanceAave();
    if (amount > 0) {
      _withdrawAave(amount);
    }
  }

  function _withdrawSomeCompound(uint256 _amount) internal {
    uint256 b = balanceCompound();
    uint256 bT = balanceCompoundInToken();
    require(bT >= _amount, "insufficient funds");
    // can have unintentional rounding errors
    uint256 amount = (b.mul(_amount)).div(bT).add(1);
    _withdrawCompound(amount);
  }

  // 1999999614570950845
  function _withdrawSomeFulcrum(uint256 _amount) internal {
    // Balance of fulcrum tokens, 1 iDAI = 1.00x DAI
    uint256 b = balanceFulcrum(); // 1970469086655766652
    // Balance of token in fulcrum
    uint256 bT = balanceFulcrumInToken(); // 2000000803224344406
    require(bT >= _amount, "insufficient funds");
    // can have unintentional rounding errors
    uint256 amount = (b.mul(_amount)).div(bT).add(1);
    _withdrawFulcrum(amount);
  }

  function _withdrawSome(uint256 _amount) internal {
    if (provider == Lender.COMPOUND) {
      _withdrawSomeCompound(_amount);
    }
    if (provider == Lender.AAVE) {
      require(balanceAave() >= _amount, "insufficient funds");
      _withdrawAave(_amount);
    }
    if (provider == Lender.DYDX) {
      require(balanceDydx() >= _amount, "insufficient funds");
      _withdrawDydx(_amount);
    }
    if (provider == Lender.FULCRUM) {
      _withdrawSomeFulcrum(_amount);
    }
  }

  function rebalance() public {
    Lender newProvider = recommend();

    if (newProvider != provider) {
      _withdrawAll();
    }

    if (balance() > 0) {
      if (newProvider == Lender.DYDX) {
        supplyDydx(balance());
      } else if (newProvider == Lender.FULCRUM) {
        supplyFulcrum(balance());
      } else if (newProvider == Lender.COMPOUND) {
        supplyCompound(balance());
      } else if (newProvider == Lender.AAVE) {
        supplyAave(balance());
      }
    }

    provider = newProvider;
  }

  // Internal only rebalance for better gas in redeem
  function _rebalance(Lender newProvider) internal {
    if (_balance() > 0) {
      if (newProvider == Lender.DYDX) {
        supplyDydx(_balance());
      } else if (newProvider == Lender.FULCRUM) {
        supplyFulcrum(_balance());
      } else if (newProvider == Lender.COMPOUND) {
        supplyCompound(_balance());
      } else if (newProvider == Lender.AAVE) {
        supplyAave(_balance());
      }
    }
    provider = newProvider;
  }

  function supplyAave(uint amount) public {
      Aave(getAave()).deposit(token, amount, 0);
  }
  function supplyFulcrum(uint amount) public {
      require(Fulcrum(fulcrum).mint(address(this), amount) > 0, "FULCRUM: supply failed");
  }
  function supplyCompound(uint amount) public {
      require(Compound(compound).mint(amount) == 0, "COMPOUND: supply failed");
  }
  function _withdrawAave(uint amount) internal {
      AToken(aaveToken).redeem(amount);
  }
  function _withdrawFulcrum(uint amount) internal {
      require(Fulcrum(fulcrum).burn(address(this), amount) > 0, "FULCRUM: withdraw failed");
  }
  function _withdrawCompound(uint amount) internal {
      require(Compound(compound).redeem(amount) == 0, "COMPOUND: withdraw failed");
  }

  function invest(uint256 _amount)
      external
      nonReentrant
  {
      require(_amount > 0, "deposit must be greater than 0");
      pool = calcPoolValueInToken();

      IERC20(token).safeTransferFrom(msg.sender, address(this), _amount);

      rebalance();

      // Calculate pool shares
      uint256 shares = 0;
      if (pool == 0) {
        shares = _amount;
        pool = _amount;
      } else {
        shares = (_amount.mul(_totalSupply)).div(pool);
      }
      pool = calcPoolValueInToken();
      _mint(msg.sender, shares);
  }

  function _calcPoolValueInToken() internal view returns (uint) {
    return _balanceCompoundInToken()
      .add(_balanceFulcrumInToken())
      .add(_balanceDydx())
      .add(_balanceAave())
      .add(_balance());
  }

  function calcPoolValueInToken() public view returns (uint) {
    return balanceCompoundInToken()
      .add(balanceFulcrumInToken())
      .add(balanceDydx())
      .add(balanceAave())
      .add(balance());
  }

  function getPricePerFullShare() public view returns (uint) {
    uint _pool = calcPoolValueInToken();
    return _pool.mul(1e18).div(_totalSupply);
  }

  // Redeem any invested tokens from the pool
  function redeem(uint256 _shares)
      external
      nonReentrant
  {
      require(_shares > 0, "withdraw must be greater than 0");

      uint256 ibalance = balanceOf(msg.sender);
      require(_shares <= ibalance, "insufficient balance");

      // Could have over value from cTokens
      pool = calcPoolValueInToken();
      // Calc to redeem before updating balances
      uint256 r = (pool.mul(_shares)).div(_totalSupply);


      _balances[msg.sender] = _balances[msg.sender].sub(_shares, "redeem amount exceeds balance");
      _totalSupply = _totalSupply.sub(_shares);

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

      // Check ETH balance
      uint256 b = IERC20(token).balanceOf(address(this));
      Lender newProvider = provider;
      if (b < r) {
        newProvider = recommend();
        if (newProvider != provider) {
          _withdrawAll();
        } else {
          _withdrawSome(r.sub(b));
        }
      }

      IERC20(token).safeTransfer(msg.sender, r);

      if (newProvider != provider) {
        _rebalance(newProvider);
      }
      pool = calcPoolValueInToken();
  }
}

Read Contract

aave 0x819faf7b → address
aaveToken 0x06a3fe59 → address
allowance 0xdd62ed3e → uint256
apr 0x57ded9c9 → address
balance 0xb69ef8a8 → uint256
balanceAave 0xcf8ca426 → uint256
balanceCompound 0x61c1ec55 → uint256
balanceCompoundInToken 0xa7287971 → uint256
balanceDydx 0x39c0a7e1 → uint256
balanceFulcrum 0x0eb2a267 → uint256
balanceFulcrumInToken 0xf5a41dea → uint256
balanceOf 0x70a08231 → uint256
calcPoolValueInToken 0x7137ef99 → uint256
compound 0xf69e2046 → address
dToken 0xd9d7858a → uint256
decimals 0x313ce567 → uint8
dydx 0x8e4ec6ef → address
fulcrum 0x58782c21 → address
getAave 0xf7c1ec77 → address
getAaveCore 0xf82ce27d → address
getPricePerFullShare 0x77c7b8fc → uint256
name 0x06fdde03 → string
pool 0x16f0115b → uint256
provider 0x085d4883 → uint8
recommend 0xa160176d → uint8
symbol 0x95d89b41 → string
token 0xfc0c546a → address
totalSupply 0x18160ddd → uint256

Write Contract 15 functions

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

approve 0x095ea7b3
address spender
uint256 amount
returns: bool
approveToken 0x99b71d5c
No parameters
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
deposit 0xb6b55f25
uint256 _amount
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
invest 0x2afcf480
uint256 _amount
rebalance 0x7d7c2a1c
No parameters
redeem 0xdb006a75
uint256 _shares
supplyAave 0x65aab749
uint256 amount
supplyCompound 0xe849d659
uint256 amount
supplyDydx 0x06636c1c
uint256 amount
returns: uint256
supplyFulcrum 0x8124955c
uint256 amount
transfer 0xa9059cbb
address recipient
uint256 amount
returns: bool
transferFrom 0x23b872dd
address sender
address recipient
uint256 amount
returns: bool
withdraw 0x2e1a7d4d
uint256 _shares

Recent Transactions

No transactions found for this address