Address: 0xA1C10036F5398601f34d11F0be7Da26a8875Fb0d
Balance (XRP): 0 XRP
Bytecode: 0x608060405234801561001057600080fd5b50600436106101fa5760003560e01c8063744bfe611161011a578063bfe7edd7116100ad578063e823f9831161007c578063e823f98314610623578063ec87621c1461063f578063ed35d7e51461065d578063fbb6272d1461068f578063fc7e286d146106bf576101fa565b8063bfe7edd714610589578063d4a89c4f146105b9578063d547741f146105e9578063e057399514610605576101fa565b8063a217fddf116100e9578063a217fddf14610501578063a90fe0e41461051f578063b4b5b48f1461053b578063b78a09311461056d576101fa565b8063744bfe611461045357806381d12c581461046f57806391d14854146104a15780639fe369c6146104d1576101fa565b806336568abe116101925780635b6ef9b8116101615780635b6ef9b8146103a75780636925aaeb146103d75780636e553f651461040757806370c1819914610423576101fa565b806336568abe14610333578063407ea8901461034f578063501883011461036b578063514ebb4214610389576101fa565b8063248a9ca3116101ce578063248a9ca314610299578063256a7997146102c95780632f2ff15d146102e75780633014b3f014610303576101fa565b80626d6cae146101ff57806301ffc9a71461021d5780630406ec651461024d578063083ec68a1461027d575b600080fd5b6102076106ef565b604051610214919061209d565b60405180910390f35b61023760048036038101906102329190612124565b6106f5565b604051610244919061216c565b60405180910390f35b610267600480360381019061026291906121b3565b61076f565b604051610274919061229e565b60405180910390f35b6102976004803603810190610292919061234a565b610859565b005b6102b360048036038101906102ae91906123c0565b6109f7565b6040516102c091906123fc565b60405180910390f35b6102d1610a16565b6040516102de9190612476565b60405180910390f35b61030160048036038101906102fc9190612491565b610a3c565b005b61031d600480360381019061031891906124d1565b610a5e565b60405161032a919061209d565b60405180910390f35b61034d60048036038101906103489190612491565b610ab4565b005b610369600480360381019061036491906124fe565b610b2f565b005b610373610d13565b604051610380919061209d565b60405180910390f35b610391610d19565b60405161039e91906123fc565b60405180910390f35b6103c160048036038101906103bc919061258d565b610d3d565b6040516103ce919061209d565b60405180910390f35b6103f160048036038101906103ec919061258d565b610fa8565b6040516103fe919061264a565b60405180910390f35b610421600480360381019061041c919061234a565b611048565b005b61043d6004803603810190610438919061266c565b61125e565b60405161044a91906126db565b60405180910390f35b61046d6004803603810190610468919061234a565b6112a9565b005b6104896004803603810190610484919061266c565b611432565b60405161049893929190612705565b60405180910390f35b6104bb60048036038101906104b69190612491565b611479565b6040516104c8919061216c565b60405180910390f35b6104eb60048036038101906104e69190612884565b6114e3565b6040516104f891906129be565b60405180910390f35b6105096115e1565b60405161051691906123fc565b60405180910390f35b6105396004803603810190610534919061266c565b6115e8565b005b6105556004803603810190610550919061266c565b611649565b604051610564939291906129e0565b60405180910390f35b61058760048036038101906105829190612a72565b611673565b005b6105a3600480360381019061059e919061266c565b611775565b6040516105b0919061216c565b60405180910390f35b6105d360048036038101906105ce9190612b3c565b6117a2565b6040516105e0919061229e565b60405180910390f35b61060360048036038101906105fe9190612491565b611af5565b005b61060d611b17565b60405161061a919061209d565b60405180910390f35b61063d60048036038101906106389190612b89565b611b1d565b005b610647611d23565b60405161065491906123fc565b60405180910390f35b6106776004803603810190610672919061266c565b611d47565b604051610686939291906129e0565b60405180910390f35b6106a960048036038101906106a4919061258d565b611d71565b6040516106b6919061216c565b60405180910390f35b6106d960048036038101906106d491906124d1565b611d91565b6040516106e6919061209d565b60405180910390f35b60025481565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610768575061076782611da9565b5b9050919050565b606060006103e867ffffffffffffffff81111561078f5761078e612741565b5b6040519080825280602002602001820160405280156107bd5781602001602082028036833780820191505090505b50905060008060025490505b6001811061084e576008600082815260200190815260200160002060020160009054906101000a900460ff1661081e578083838151811061080d5761080c612bc9565b5b602002602001018181525050610824565b8461084e575b818061082f90612c27565b925050825182031561084e57808061084690612c6f565b9150506107c9565b508192505050919050565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0861088381611e13565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016108df9190612ca7565b602060405180830381865afa1580156108fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109209190612cd7565b1015610958576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546109a79190612d04565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16837f21d3f238b5a9e25ffc48b8320bc1d58882b1d90d0b4fcc7ba9707e3aebfedf1660405160405180910390a3505050565b6000806000838152602001908152602001600020600101549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610a45826109f7565b610a4e81611e13565b610a588383611e27565b50505050565b6000600354600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610aad9190612d67565b9050919050565b610abc611f18565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b20576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2a8282611f20565b505050565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08610b5981611e13565b83600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015610bd2576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610c219190612d98565b92505081905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83866040518363ffffffff1660e01b8152600401610c85929190612dcc565b6020604051808303816000875af1158015610ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc89190612e0a565b508273ffffffffffffffffffffffffffffffffffffffff16847fb43836bc2d33817133827d193082cf79e6dbd856bfe9e6fe812baaa0f970aed260405160405180910390a350505050565b60045481565b7f4d9863970d41475dce450df64b8c3f5625245716124ab2023150cc6828d194c481565b6000600560008363ffffffff1663ffffffff16815260200190815260200160002060009054906101000a900460ff16610da2576040517fe1478bb000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600354600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015610e1d576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600354600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610e6e9190612d98565b9250508190555060035460046000828254610e899190612d04565b9250508190555060026000815480929190610ea390612c27565b9190505550600060405180606001604052808463ffffffff1681526020014281526020016000151581525090508060086000600254815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff1602179055506020820151816001015560408201518160020160006101000a81548160ff021916908315150217905550905050600660008463ffffffff1663ffffffff168152602001908152602001600020604051610f669190612f3a565b60405180910390206002547feb82ddf033f40993b9d3e74f96214944168d3c6a1001f991ce326f44f84a8df460405160405180910390a3600254915050919050565b60066020528060005260406000206000915090508054610fc790612e66565b80601f0160208091040260200160405190810160405280929190818152602001828054610ff390612e66565b80156110405780601f1061101557610100808354040283529160200191611040565b820191906000526020600020905b81548152906001019060200180831161102357829003601f168201915b505050505081565b81600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016110a49190612ca7565b602060405180830381865afa1580156110c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e59190612cd7565b101561111d576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b815260040161117c93929190612f51565b6020604051808303816000875af115801561119b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111bf9190612e0a565b5081600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461120f9190612d04565b925050819055508073ffffffffffffffffffffffffffffffffffffffff16827f21d3f238b5a9e25ffc48b8320bc1d58882b1d90d0b4fcc7ba9707e3aebfedf1660405160405180910390a35050565b611266612063565b6009600083815260200190815260200160002060405180606001604052908160008201548152602001600182015481526020016002820154815250509050919050565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086112d381611e13565b82600454101561130f576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080841161132057600454611322565b835b905080600460008282546113369190612d98565b92505081905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84836040518363ffffffff1660e01b815260040161139a929190612dcc565b6020604051808303816000875af11580156113b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113dd9190612e0a565b508273ffffffffffffffffffffffffffffffffffffffff167fef2e7b9687fb6d973600bec02a1a09e5501f486d1078900dc6b9af0e4bdbf86d82604051611424919061209d565b60405180910390a250505050565b60086020528060005260406000206000915090508060000160009054906101000a900463ffffffff16908060010154908060020160009054906101000a900460ff16905083565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60606000825167ffffffffffffffff81111561150257611501612741565b5b60405190808252806020026020018201604052801561153b57816020015b611528612063565b8152602001906001900390816115205790505b50905060005b83518110156115d7576007600085838151811061156157611560612bc9565b5b602002602001015163ffffffff16815260200190815260200160002060405180606001604052908160008201548152602001600182015481526020016002820154815250508282815181106115b9576115b8612bc9565b5b602002602001018190525080806115cf90612c27565b915050611541565b5080915050919050565b6000801b81565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0861161281611e13565b816003819055507f4fc4e188cbba3a5874bd8b4a512e6ca9a95f5f5efbb5eba29cdd33aeeb2121c260405160405180910390a15050565b60076020528060005260406000206000915090508060000154908060010154908060020154905083565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0861169d81611e13565b8383600660008863ffffffff1663ffffffff16815260200190815260200160002091826116cb929190613120565b5081600560008763ffffffff1663ffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600660008663ffffffff1663ffffffff16815260200190815260200160002060405161172f9190612f3a565b60405180910390207f6df0f76f30536e84e97366618818272ba2bb49ee7b5f923ffce09eefe45b2efd83604051611766919061216c565b60405180910390a25050505050565b60006008600083815260200190815260200160002060020160009054906101000a900460ff169050919050565b6060600083839050905060008167ffffffffffffffff8111156117c8576117c7612741565b5b6040519080825280602002602001820160405280156117f65781602001602082028036833780820191505090505b5090508160035461180791906131f0565b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561187f576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160035461188d91906131f0565b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546118db9190612d98565b92505081905550816003546118f091906131f0565b600460008282546119019190612d04565b9250508190555060005b85859050811015611ae957600086868381811061192b5761192a612bc9565b5b9050602002016020810190611940919061258d565b9050600560008263ffffffff1663ffffffff16815260200190815260200160002060009054906101000a900460ff166119a5576040517fe1478bb000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260008154809291906119b890612c27565b9190505550600060405180606001604052808363ffffffff1681526020014281526020016000151581525090508060086000600254815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff1602179055506020820151816001015560408201518160020160006101000a81548160ff021916908315150217905550905050600660008363ffffffff1663ffffffff168152602001908152602001600020604051611a7b9190612f3a565b60405180910390206002547feb82ddf033f40993b9d3e74f96214944168d3c6a1001f991ce326f44f84a8df460405160405180910390a3600254848481518110611ac857611ac7612bc9565b5b60200260200101818152505050508080611ae190612c27565b91505061190b565b50809250505092915050565b611afe826109f7565b611b0781611e13565b611b118383611f20565b50505050565b60035481565b7f4d9863970d41475dce450df64b8c3f5625245716124ab2023150cc6828d194c4611b4781611e13565b611b5082611775565b15611b87576040517f4a4117f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008311611bc1576040517faa7feadc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518060600160405280428152602001858152602001848152509050600760006008600086815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16815260200190815260200160002060000154421115611c8c5780600760006008600087815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff1681526020019081526020016000206000820151816000015560208201518160010155604082015181600201559050505b806009600085815260200190815260200160002060008201518160000155602082015181600101556040820151816002015590505060016008600085815260200190815260200160002060020160006101000a81548160ff021916908315150217905550827fb9e6c466a22353ea5aaf46595d2883b396bbdd87425257bcd8b207883d6c5af660405160405180910390a250505050565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b60096020528060005260406000206000915090508060000154908060010154908060020154905083565b60056020528060005260406000206000915054906101000a900460ff1681565b600a6020528060005260406000206000915090505481565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b611e2481611e1f611f18565b612012565b50565b6000611e338383611479565b611f0d57600160008085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611eaa611f18565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611f12565b600090505b92915050565b600033905090565b6000611f2c8383611479565b1561200757600080600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611fa4611f18565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a46001905061200c565b600090505b92915050565b61201c8282611479565b61205f5780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401612056929190613232565b60405180910390fd5b5050565b60405180606001604052806000815260200160008152602001600081525090565b6000819050919050565b61209781612084565b82525050565b60006020820190506120b2600083018461208e565b92915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612101816120cc565b811461210c57600080fd5b50565b60008135905061211e816120f8565b92915050565b60006020828403121561213a576121396120c2565b5b60006121488482850161210f565b91505092915050565b60008115159050919050565b61216681612151565b82525050565b6000602082019050612181600083018461215d565b92915050565b61219081612151565b811461219b57600080fd5b50565b6000813590506121ad81612187565b92915050565b6000602082840312156121c9576121c86120c2565b5b60006121d78482850161219e565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61221581612084565b82525050565b6000612227838361220c565b60208301905092915050565b6000602082019050919050565b600061224b826121e0565b61225581856121eb565b9350612260836121fc565b8060005b83811015612291578151612278888261221b565b975061228383612233565b925050600181019050612264565b5085935050505092915050565b600060208201905081810360008301526122b88184612240565b905092915050565b6122c981612084565b81146122d457600080fd5b50565b6000813590506122e6816122c0565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612317826122ec565b9050919050565b6123278161230c565b811461233257600080fd5b50565b6000813590506123448161231e565b92915050565b60008060408385031215612361576123606120c2565b5b600061236f858286016122d7565b925050602061238085828601612335565b9150509250929050565b6000819050919050565b61239d8161238a565b81146123a857600080fd5b50565b6000813590506123ba81612394565b92915050565b6000602082840312156123d6576123d56120c2565b5b60006123e4848285016123ab565b91505092915050565b6123f68161238a565b82525050565b600060208201905061241160008301846123ed565b92915050565b6000819050919050565b600061243c612437612432846122ec565b612417565b6122ec565b9050919050565b600061244e82612421565b9050919050565b600061246082612443565b9050919050565b61247081612455565b82525050565b600060208201905061248b6000830184612467565b92915050565b600080604083850312156124a8576124a76120c2565b5b60006124b6858286016123ab565b92505060206124c785828601612335565b9150509250929050565b6000602082840312156124e7576124e66120c2565b5b60006124f584828501612335565b91505092915050565b600080600060608486031215612517576125166120c2565b5b6000612525868287016122d7565b935050602061253686828701612335565b925050604061254786828701612335565b9150509250925092565b600063ffffffff82169050919050565b61256a81612551565b811461257557600080fd5b50565b60008135905061258781612561565b92915050565b6000602082840312156125a3576125a26120c2565b5b60006125b184828501612578565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156125f45780820151818401526020810190506125d9565b60008484015250505050565b6000601f19601f8301169050919050565b600061261c826125ba565b61262681856125c5565b93506126368185602086016125d6565b61263f81612600565b840191505092915050565b600060208201905081810360008301526126648184612611565b905092915050565b600060208284031215612682576126816120c2565b5b6000612690848285016122d7565b91505092915050565b6060820160008201516126af600085018261220c565b5060208201516126c2602085018261220c565b5060408201516126d5604085018261220c565b50505050565b60006060820190506126f06000830184612699565b92915050565b6126ff81612551565b82525050565b600060608201905061271a60008301866126f6565b612727602083018561208e565b612734604083018461215d565b949350505050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61277982612600565b810181811067ffffffffffffffff8211171561279857612797612741565b5b80604052505050565b60006127ab6120b8565b90506127b78282612770565b919050565b600067ffffffffffffffff8211156127d7576127d6612741565b5b602082029050602081019050919050565b600080fd5b60006128006127fb846127bc565b6127a1565b90508083825260208201905060208402830185811115612823576128226127e8565b5b835b8181101561284c57806128388882612578565b845260208401935050602081019050612825565b5050509392505050565b600082601f83011261286b5761286a61273c565b5b813561287b8482602086016127ed565b91505092915050565b60006020828403121561289a576128996120c2565b5b600082013567ffffffffffffffff8111156128b8576128b76120c7565b5b6128c484828501612856565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60608201600082015161290f600085018261220c565b506020820151612922602085018261220c565b506040820151612935604085018261220c565b50505050565b600061294783836128f9565b60608301905092915050565b6000602082019050919050565b600061296b826128cd565b61297581856128d8565b9350612980836128e9565b8060005b838110156129b1578151612998888261293b565b97506129a383612953565b925050600181019050612984565b5085935050505092915050565b600060208201905081810360008301526129d88184612960565b905092915050565b60006060820190506129f5600083018661208e565b612a02602083018561208e565b612a0f604083018461208e565b949350505050565b600080fd5b60008083601f840112612a3257612a3161273c565b5b8235905067ffffffffffffffff811115612a4f57612a4e612a17565b5b602083019150836001820283011115612a6b57612a6a6127e8565b5b9250929050565b60008060008060608587031215612a8c57612a8b6120c2565b5b6000612a9a87828801612578565b945050602085013567ffffffffffffffff811115612abb57612aba6120c7565b5b612ac787828801612a1c565b93509350506040612ada8782880161219e565b91505092959194509250565b60008083601f840112612afc57612afb61273c565b5b8235905067ffffffffffffffff811115612b1957612b18612a17565b5b602083019150836020820283011115612b3557612b346127e8565b5b9250929050565b60008060208385031215612b5357612b526120c2565b5b600083013567ffffffffffffffff811115612b7157612b706120c7565b5b612b7d85828601612ae6565b92509250509250929050565b60008060408385031215612ba057612b9f6120c2565b5b6000612bae858286016122d7565b9250506020612bbf858286016122d7565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612c3282612084565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612c6457612c63612bf8565b5b600182019050919050565b6000612c7a82612084565b915060008203612c8d57612c8c612bf8565b5b600182039050919050565b612ca18161230c565b82525050565b6000602082019050612cbc6000830184612c98565b92915050565b600081519050612cd1816122c0565b92915050565b600060208284031215612ced57612cec6120c2565b5b6000612cfb84828501612cc2565b91505092915050565b6000612d0f82612084565b9150612d1a83612084565b9250828201905080821115612d3257612d31612bf8565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612d7282612084565b9150612d7d83612084565b925082612d8d57612d8c612d38565b5b828204905092915050565b6000612da382612084565b9150612dae83612084565b9250828203905081811115612dc657612dc5612bf8565b5b92915050565b6000604082019050612de16000830185612c98565b612dee602083018461208e565b9392505050565b600081519050612e0481612187565b92915050565b600060208284031215612e2057612e1f6120c2565b5b6000612e2e84828501612df5565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680612e7e57607f821691505b602082108103612e9157612e90612e37565b5b50919050565b600081905092915050565b60008190508160005260206000209050919050565b60008154612ec481612e66565b612ece8186612e97565b94506001821660008114612ee95760018114612efe57612f31565b60ff1983168652811515820286019350612f31565b612f0785612ea2565b60005b83811015612f2957815481890152600182019150602081019050612f0a565b838801955050505b50505092915050565b6000612f468284612eb7565b915081905092915050565b6000606082019050612f666000830186612c98565b612f736020830185612c98565b612f80604083018461208e565b949350505050565b600082905092915050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302612fe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82612fa3565b612fea8683612fa3565b95508019841693508086168417925050509392505050565b600061301d61301861301384612084565b612417565b612084565b9050919050565b6000819050919050565b61303783613002565b61304b61304382613024565b848454612fb0565b825550505050565b600090565b613060613053565b61306b81848461302e565b505050565b5b8181101561308f57613084600082613058565b600181019050613071565b5050565b601f8211156130d4576130a581612ea2565b6130ae84612f93565b810160208510156130bd578190505b6130d16130c985612f93565b830182613070565b50505b505050565b600082821c905092915050565b60006130f7600019846008026130d9565b1980831691505092915050565b600061311083836130e6565b9150826002028217905092915050565b61312a8383612f88565b67ffffffffffffffff81111561314357613142612741565b5b61314d8254612e66565b613158828285613093565b6000601f8311600181146131875760008415613175578287013590505b61317f8582613104565b8655506131e7565b601f19841661319586612ea2565b60005b828110156131bd57848901358255600182019150602085019450602081019050613198565b868310156131da57848901356131d6601f8916826130e6565b8355505b6001600288020188555050505b50505050505050565b60006131fb82612084565b915061320683612084565b925082820261321481612084565b9150828204841483151761322b5761322a612bf8565b5b5092915050565b60006040820190506132476000830185612c98565b61325460208301846123ed565b939250505056fea2646970667358221220f3435b531978bbce5e281dd517b20c0fb0a9766d0fa16da27fe126c754a9316a64736f6c63430008140033
Oracle.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract Oracle is AccessControl { bytes32 public constant RESPONDER_ROLE = keccak256("RESPONDER_ROLE"); bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); IERC20 public syloToken; struct Request { uint32 tokenId; uint256 timestamp; bool processed; } struct Response { uint256 timestamp; uint256 value; uint256 requestId; } uint256 public requestId = 0; uint256 public pricePerRequest = 10 ether; // 10 SYLO uint256 public withdrawable = 0; mapping(uint32 => bool) public tokens; // tokenId => bool mapping(uint32 => string) public tokenNames; // tokenId => string mapping(uint256 => Response) public tokenData; // requestId => Response mapping(uint256 => Request) public requests; // requestId => Request mapping(uint256 => Response) public responses; // requestId => Response mapping(address => uint256) public deposits; // wallet => amount /** Events */ event Requested(uint256 indexed requestId, string indexed token); event Responded(uint256 indexed requestId); event TokenUpdated(string indexed token, bool state); event Deposited(uint256 indexed amount, address indexed sender); event WithdrawalForUser(uint256 indexed amount, address indexed from); event AdminWithdrawal(uint256 amount, address indexed recipient); event UpdatedAmountPerRequest(); /** Errors */ error AlreadyFulfilled(); error NotAllowedToken(); error InvalidValue(); error InsufficientBalance(); constructor( address _responder, uint32[] memory _tokens, IERC20 _syloToken, address _initialManager ) { /** Grant roles */ _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); grantRole(RESPONDER_ROLE, _responder); grantRole(MANAGER_ROLE, _initialManager); /** Set root token */ syloToken = _syloToken; /** Set initial allowed tokens */ for (uint256 i = 0; i < _tokens.length; i++) { tokens[_tokens[i]] = true; } } /** * @notice Request fresh data * @param _token - The desired token */ function createRequest(uint32 _token) public returns (uint) { if (!tokens[_token]) revert NotAllowedToken(); if (deposits[msg.sender] < pricePerRequest) revert InsufficientBalance(); deposits[msg.sender] -= pricePerRequest; withdrawable += pricePerRequest; requestId++; Request memory request = Request(_token, block.timestamp, false); requests[requestId] = request; emit Requested({requestId: requestId, token: tokenNames[_token]}); return requestId; } /** * @notice Request fresh data * @param _tokens - The desired token */ function createRequests( uint32[] calldata _tokens ) public returns (uint[] memory) { uint256 am = _tokens.length; uint[] memory requestIds = new uint[](am); if (deposits[msg.sender] < (pricePerRequest * am)) revert InsufficientBalance(); deposits[msg.sender] -= (pricePerRequest * am); withdrawable += (pricePerRequest * am); for (uint256 i = 0; i < _tokens.length; i++) { uint32 _token = _tokens[i]; if (!tokens[_token]) revert NotAllowedToken(); requestId++; Request memory request = Request(_token, block.timestamp, false); requests[requestId] = request; emit Requested({requestId: requestId, token: tokenNames[_token]}); requestIds[i] = requestId; } return requestIds; } /** * @notice Get response * @param _requestId - The requestId */ function getResponse( uint256 _requestId ) public view returns (Response memory) { return responses[_requestId]; } /** * @notice Check whether requestId was processed * @param _requestId - The requestId */ function isProcessed(uint256 _requestId) public view returns (bool) { return requests[_requestId].processed; } /** * @notice Get pending requests */ function getPendingRequests( bool _breakOnProcessed ) public view returns (uint[] memory) { uint[] memory requestIds = new uint[](1000); uint256 index = 0; for (uint256 i = requestId; i >= 1; i--) { if (!requests[i].processed) { requestIds[index] = i; } else { if (_breakOnProcessed) { break; } } index++; if (index == requestIds.length) { break; } } return requestIds; } /** * @notice Get latest token data * @param _tokens - Array of tokens */ function getLatestData( uint32[] memory _tokens ) public view returns (Response[] memory) { Response[] memory x = new Response[](_tokens.length); for (uint256 i = 0; i < _tokens.length; i++) { x[i] = tokenData[_tokens[i]]; } return x; } /** * @notice Deposit ROOT into the contract * @param _amount - The amount you wish to deposit * @param _sender - Whoever gets the amount */ function deposit(uint256 _amount, address _sender) external { if (syloToken.balanceOf(msg.sender) < _amount) revert InsufficientBalance(); syloToken.transferFrom(msg.sender, address(this), _amount); deposits[_sender] += _amount; emit Deposited({amount: _amount, sender: _sender}); } /** * @notice Get the remaining requests for an address * @param _address - The address */ function getRemainingRequests(address _address) public view returns (uint) { return deposits[_address] / pricePerRequest; } /** Admin functions */ /** * @notice Allows admin to create response for request * @param _value - The data * @param _requestId - The requestId */ function createResponse( uint256 _value, uint256 _requestId ) external onlyRole(RESPONDER_ROLE) { if (isProcessed(_requestId)) revert AlreadyFulfilled(); if (_value <= 0) revert InvalidValue(); Response memory response = Response( block.timestamp, _value, _requestId ); if ( block.timestamp > tokenData[requests[_requestId].tokenId].timestamp ) { tokenData[requests[_requestId].tokenId] = response; } responses[_requestId] = response; requests[_requestId].processed = true; emit Responded({requestId: _requestId}); } /** * @notice Allow or disallow a token * @param _token - The token symbol * @param _state - true/false */ function updateToken( uint32 _token, string calldata _name, bool _state ) external onlyRole(MANAGER_ROLE) { tokenNames[_token] = _name; tokens[_token] = _state; emit TokenUpdated({token: tokenNames[_token], state: _state}); } /** * @notice Allows admin to withdraw tokens to a desired wallet for a user * @param _amount - The amount of ROOT * @param _from - The address to deduct from * @param _recipient - The to address */ function withdrawForUser( uint256 _amount, address _from, address _recipient ) external onlyRole(MANAGER_ROLE) { if (deposits[_from] < _amount) revert InsufficientBalance(); deposits[_from] -= _amount; syloToken.transfer(_recipient, _amount); emit WithdrawalForUser({amount: _amount, from: _from}); } function depositForUser( uint256 _amount, address _recipient ) external onlyRole(MANAGER_ROLE) { if (syloToken.balanceOf(address(this)) < _amount) revert InsufficientBalance(); deposits[_recipient] += _amount; emit Deposited({amount: _amount, sender: _recipient}); } /** * @notice Allows admin to update pricing * @param _amount - The new price */ function updateAmountPerRequest( uint256 _amount ) external onlyRole(MANAGER_ROLE) { pricePerRequest = _amount; emit UpdatedAmountPerRequest(); } /** * @notice Allows admin to withdraw withdrawable funds * @param _recipient - The to address */ function withdrawFunds( uint256 _amount, address _recipient ) external onlyRole(MANAGER_ROLE) { if (withdrawable < _amount) revert InsufficientBalance(); uint256 amount = _amount > 0 ? _amount : withdrawable; withdrawable -= amount; syloToken.transfer(_recipient, amount); emit AdminWithdrawal(amount, _recipient); } }
AccessControl.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
IAccessControl.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
ERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
IERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
Gas Token: