Address: 0x870bC2604D6EAC536c791A603bFDE1A1448e168e
Balance (XRP): 0 XRP
Bytecode: 0x608060405234801561001057600080fd5b50600436106102415760003560e01c80638b95dd7111610145578063c8690233116100bd578063e32954eb1161008c578063e985e9c511610071578063e985e9c5146105d3578063f1cb7e061461060f578063f2fde38b1461062257600080fd5b8063e32954eb146105ad578063e59d895d146105c057600080fd5b8063c8690233146104ea578063ce3decdc14610544578063d5fa2b0014610557578063d700ff331461056a57600080fd5b8063a8fa568211610114578063ac9650d8116100f9578063ac9650d8146104a4578063af4a5f6d146104c4578063bc1c58d1146104d757600080fd5b8063a8fa56821461044d578063a9784b3e1461046057600080fd5b80638b95dd71146104035780638da5cb5b14610416578063a22cb46514610427578063a4b91a011461043a57600080fd5b806337bf7a2f116101d85780635c98042b116101a7578063691f34311161018c578063691f3431146103d5578063715018a6146103e857806377372213146103f057600080fd5b80635c98042b146103af578063623195b0146103c257600080fd5b806337bf7a2f1461031b5780633b3b57de1461032e5780634cbf6ba41461034157806359d1d43c1461038f57600080fd5b80632203ab56116102145780632203ab56146102c157806329cd62ea146102e2578063304e6ade146102f55780633603d7581461030857600080fd5b806301ffc9a7146102465780630af179d71461026e57806310f13a8c14610283578063124a319c14610296575b600080fd5b6102596102543660046127a1565b610635565b60405190151581526020015b60405180910390f35b61028161027c3660046127fe565b610646565b005b61028161029136600461284a565b610852565b6102a96102a43660046128c4565b610921565b6040516001600160a01b039091168152602001610265565b6102d46102cf3660046128f0565b610bcf565b604051610265929190612962565b6102816102f036600461297b565b610d07565b6102816103033660046127fe565b610da9565b6102816103163660046129a7565b610e27565b600c546102a9906001600160a01b031681565b6102a961033c3660046129a7565b610ecc565b61025961034f3660046128f0565b60008281526001602090815260408083205467ffffffffffffffff1683526007825280832094835293815283822092825291909152205461ffff16151590565b6103a261039d3660046127fe565b610efe565b60405161026591906129c0565b6103a26103bd3660046129a7565b610fe0565b6102816103d03660046129d3565b6110a1565b6103a26103e33660046129a7565b611140565b61028161117c565b6102816103fe3660046127fe565b611190565b610281610411366004612a3c565b61120e565b6000546001600160a01b03166102a9565b610281610435366004612b25565b6112f0565b610281610448366004612b51565b6113df565b6103a261045b366004612b8f565b6114ac565b61025961046e366004612bcf565b6001600160a01b039283166000908152600e60209081526040808320948352938152838220929094168152925290205460ff1690565b6104b76104b2366004612c4b565b6114fc565b6040516102659190612c8d565b6102816104d2366004612cef565b61150a565b6103a26104e53660046129a7565b611573565b61052f6104f83660046129a7565b60008181526001602081815260408084205467ffffffffffffffff168452600a825280842094845293905291902080549101549091565b60408051928352602083019190915201610265565b6102816105523660046127fe565b6115af565b610281610565366004612d0c565b6116f4565b6105946105783660046129a7565b60016020526000908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610265565b6104b76105bb366004612d3c565b61171b565b6102816105ce366004612d7b565b611730565b6102596105e1366004612db0565b6001600160a01b039182166000908152600d6020908152604080832093909416825291909152205460ff1690565b6103a261061d3660046128f0565b6117e6565b610281610630366004612cef565b6118b0565b600061064082611940565b92915050565b826106508161197e565b61065957600080fd5b6000848152600160209081526040808320548151601f870184900484028101840190925285825283926060928392859267ffffffffffffffff9091169183916106c19183918d908d90819084018382808284376000920191909152509293925050611bc89050565b90505b805151602082015110156107eb578661ffff1660000361072957806040015196506106ee81611c29565b9450846040516020016107019190612dde565b60405160208183030381529060405280519060200120925061072281611c4a565b93506107dd565b600061073482611c29565b9050816040015161ffff168861ffff1614158061075857506107568682611c66565b155b156107db576107b48c878a8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505060208801518d91506107ab908290612e10565b8b51158a611c84565b8160400151975081602001519650809550858051906020012093506107d882611c4a565b94505b505b6107e681611ef1565b6106c4565b50835115610846576108468a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c925061083d91508290508f612e10565b89511588611c84565b50505050505050505050565b8461085c8161197e565b61086557600080fd5b60008681526001602090815260408083205467ffffffffffffffff168352600b8252808320898452909152908190209051849184916108a79089908990612e23565b908152602001604051809103902091826108c2929190612ebb565b5084846040516108d3929190612e23565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a1878787876040516109119493929190612fa4565b60405180910390a3505050505050565b60008281526001602090815260408083205467ffffffffffffffff1683526008825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b03168015610977579050610640565b600061098285610ecc565b90506001600160a01b03811661099d57600092505050610640565b6040516301ffc9a760e01b602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b17905251610a0a9190612dde565b600060405180830381855afa9150503d8060008114610a45576040519150601f19603f3d011682016040523d82523d6000602084013e610a4a565b606091505b5091509150811580610a5d575060208151105b80610a9f575080601f81518110610a7657610a76612fd6565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610ab1576000945050505050610640565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b17905251610b1c9190612dde565b600060405180830381855afa9150503d8060008114610b57576040519150601f19603f3d011682016040523d82523d6000602084013e610b5c565b606091505b509092509050811580610b70575060208151105b80610bb2575080601f81518110610b8957610b89612fd6565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610bc4576000945050505050610640565b509095945050505050565b60008281526001602081815260408084205467ffffffffffffffff1684526002825280842086855290915282206060915b848111610ce75780851615801590610c30575060008181526020839052604081208054610c2c90612e33565b9050115b15610cdf5780826000838152602001908152602001600020808054610c5490612e33565b80601f0160208091040260200160405190810160405280929190818152602001828054610c8090612e33565b8015610ccd5780601f10610ca257610100808354040283529160200191610ccd565b820191906000526020600020905b815481529060010190602001808311610cb057829003601f168201915b50505050509050935093505050610d00565b60011b610c00565b5060006040518060200160405280600081525092509250505b9250929050565b82610d118161197e565b610d1a57600080fd5b6040805180820182528481526020808201858152600088815260018084528582205467ffffffffffffffff168252600a84528582208a835290935284902092518355519101555184907f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4690610d9b9086908690918252602082015260400190565b60405180910390a250505050565b82610db38161197e565b610dbc57600080fd5b60008481526001602090815260408083205467ffffffffffffffff168352600482528083208784529091529020610df4838583612ebb565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788484604051610d9b929190612fec565b80610e318161197e565b610e3a57600080fd5b6000828152600160205260408120805467ffffffffffffffff1691610e5e83613000565b82546101009290920a67ffffffffffffffff8181021990931691831602179091556000848152600160209081526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b600080610eda83603c6117e6565b90508051600003610eee5750600092915050565b610ef781611fd9565b9392505050565b60008381526001602090815260408083205467ffffffffffffffff168352600b825280832086845290915290819020905160609190610f409085908590612e23565b90815260200160405180910390208054610f5990612e33565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8590612e33565b8015610fd25780601f10610fa757610100808354040283529160200191610fd2565b820191906000526020600020905b815481529060010190602001808311610fb557829003601f168201915b505050505090509392505050565b60008181526001602090815260408083205467ffffffffffffffff16835260058252808320848452909152902080546060919061101c90612e33565b80601f016020809104026020016040519081016040528092919081815260200182805461104890612e33565b80156110955780601f1061106a57610100808354040283529160200191611095565b820191906000526020600020905b81548152906001019060200180831161107857829003601f168201915b50505050509050919050565b836110ab8161197e565b6110b457600080fd5b836110c0600182612e10565b16156110cb57600080fd5b60008581526001602090815260408083205467ffffffffffffffff168352600282528083208884528252808320878452909152902061110b838583612ebb565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe390600090a35050505050565b60008181526001602090815260408083205467ffffffffffffffff16835260098252808320848452909152902080546060919061101c90612e33565b611184612001565b61118e600061205b565b565b8261119a8161197e565b6111a357600080fd5b60008481526001602090815260408083205467ffffffffffffffff1683526009825280832087845290915290206111db838583612ebb565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051610d9b929190612fec565b826112188161197e565b61122157600080fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528484604051611253929190612962565b60405180910390a2603c83036112aa57837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd261128e84611fd9565b6040516001600160a01b03909116815260200160405180910390a25b60008481526001602090815260408083205467ffffffffffffffff16835260038252808320878452825280832086845290915290206112e98382613027565b5050505050565b6001600160a01b03821633036113735760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b336000818152600d602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6001600160a01b03821633036114375760405162461bcd60e51b815260206004820181905260248201527f53657474696e672064656c65676174652073746174757320666f722073656c66604482015260640161136a565b336000818152600e6020908152604080832087845282528083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519384529286917ff0ddb3b04746704017f9aa8bd728fcc2c1d11675041205350018915f5e4750a0910160405180910390a4505050565b60008381526001602090815260408083205467ffffffffffffffff168352600682528083208684528252808320858452825280832061ffff851684529091529020805460609190610f5990612e33565b6060610ef7600084846120b8565b611512612001565b600c805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fce2e2e1724acf0f5ef60c073fbcfd8397846d9c7fb9c7c0d99ab8e4828449f179060200160405180910390a150565b60008181526001602090815260408083205467ffffffffffffffff16835260048252808320848452909152902080546060919061101c90612e33565b826115b98161197e565b6115c257600080fd5b60008481526001602090815260408083205467ffffffffffffffff1680845260058352818420888552909252822080549192916115fe90612e33565b80601f016020809104026020016040519081016040528092919081815260200182805461162a90612e33565b80156116775780601f1061164c57610100808354040283529160200191611677565b820191906000526020600020905b81548152906001019060200180831161165a57829003601f168201915b5050505067ffffffffffffffff841660009081526005602090815260408083208b845290915290209192506116af9050858783612ebb565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f858287876040516116e4939291906130e7565b60405180910390a2505050505050565b816116fe8161197e565b61170757600080fd5b61171683603c61041185612291565b505050565b60606117288484846120b8565b949350505050565b8261173a8161197e565b61174357600080fd5b60008481526001602090815260408083205467ffffffffffffffff1683526008825280832087845282528083206001600160e01b0319871680855290835292819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b60008281526001602090815260408083205467ffffffffffffffff168352600382528083208584528252808320848452909152902080546060919061182a90612e33565b80601f016020809104026020016040519081016040528092919081815260200182805461185690612e33565b80156118a35780601f10611878576101008083540402835291602001916118a3565b820191906000526020600020905b81548152906001019060200180831161188657829003601f168201915b5050505050905092915050565b6118b8612001565b6001600160a01b0381166119345760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161136a565b61193d8161205b565b50565b60006001600160e01b031982167f59d1d43c0000000000000000000000000000000000000000000000000000000014806106405750610640826122ca565b600c546000906001600160a01b03163314806119c25750336001600160a01b037f000000000000000000000000fff7719aab38eade6a1cfda864a174b715e9d67316145b156119cf57506001919050565b6040517f02571be3000000000000000000000000000000000000000000000000000000008152600481018390526000907f000000000000000000000000ec58c26b8e0a4bc0fe1ad21d216e4ecad9e037a86001600160a01b0316906302571be390602401602060405180830381865afa158015611a50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a749190613117565b90507f00000000000000000000000044640d662a423d738d5ebf8b51e57afc0f2cf4df6001600160a01b0316816001600160a01b031603611b54576040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000044640d662a423d738d5ebf8b51e57afc0f2cf4df6001600160a01b031690636352211e90602401602060405180830381865afa158015611b2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b519190613117565b90505b6001600160a01b038116331480611b8e57506001600160a01b0381166000908152600d6020908152604080832033845290915290205460ff165b80610ef757506001600160a01b0381166000908152600e60209081526040808320868452825280832033845290915290205460ff16610ef7565b611c166040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c0810182905261064081611ef1565b6020810151815160609161064091611c419082612308565b84519190612362565b60a081015160c082015160609161064091611c41908290612e10565b600081518351148015610ef75750610ef783600084600087516123d9565b865160208801206000611c98878787612362565b90508315611dc25767ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611ce390612e33565b159050611d425767ffffffffffffffff831660009081526007602090815260408083208d845282528083208584529091528120805461ffff1691611d2683613134565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c1684529091528120611d8391612736565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a604051611db5929190613152565b60405180910390a2610846565b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611e0590612e33565b9050600003611e665767ffffffffffffffff831660009081526007602090815260408083208d845282528083208584529091528120805461ffff1691611e4a83613178565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c1684529091529020611ea88282613027565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a84604051611edd9392919061318f565b60405180910390a250505050505050505050565b60c08101516020820181905281515111611f085750565b6000611f1c82600001518360200151612308565b8260200151611f2b91906131be565b8251909150611f3a90826123fc565b61ffff166040830152611f4e6002826131be565b8251909150611f5d90826123fc565b61ffff166060830152611f716002826131be565b8251909150611f809082612424565b63ffffffff166080830152611f966004826131be565b8251909150600090611fa890836123fc565b61ffff169050611fb96002836131be565b60a084018190529150611fcc81836131be565b60c0909301929092525050565b60008151601414611fe957600080fd5b50602001516c01000000000000000000000000900490565b6000546001600160a01b0316331461118e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161136a565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60608167ffffffffffffffff8111156120d3576120d3612a26565b60405190808252806020026020018201604052801561210657816020015b60608152602001906001900390816120f15790505b50905060005b828110156122895784156121d157600084848381811061212e5761212e612fd6565b905060200281019061214091906131d1565b61214f91602491600491613218565b61215891613242565b90508581146121cf5760405162461bcd60e51b815260206004820152603460248201527f6d756c746963616c6c3a20416c6c207265636f726473206d757374206861766560448201527f2061206d61746368696e67206e616d6568617368000000000000000000000000606482015260840161136a565b505b600080308686858181106121e7576121e7612fd6565b90506020028101906121f991906131d1565b604051612207929190612e23565b600060405180830381855af49150503d8060008114612242576040519150601f19603f3d011682016040523d82523d6000602084013e612247565b606091505b50915091508161225657600080fd5b8084848151811061226957612269612fd6565b60200260200101819052505050808061228190613260565b91505061210c565b509392505050565b6040805160148082528183019092526060916020820181803683375050506c010000000000000000000000009290920260208301525090565b60006001600160e01b031982167fc869023300000000000000000000000000000000000000000000000000000000148061064057506106408261244e565b6000815b8351811061231c5761231c613279565b6000612328858361248c565b60ff1690506123388160016131be565b61234290836131be565b9150806000036123525750612358565b5061230c565b6117288382612e10565b825160609061237183856131be565b111561237c57600080fd5b60008267ffffffffffffffff81111561239757612397612a26565b6040519080825280601f01601f1916602001820160405280156123c1576020820181803683370190505b50905060208082019086860101610bc48282876124b0565b60006123e6848484612506565b6123f1878785612506565b149695505050505050565b815160009061240c8360026131be565b111561241757600080fd5b50016002015161ffff1690565b81516000906124348360046131be565b111561243f57600080fd5b50016004015163ffffffff1690565b60006001600160e01b031982167f691f343100000000000000000000000000000000000000000000000000000000148061064057506106408261252a565b60008282815181106124a0576124a0612fd6565b016020015160f81c905092915050565b602081106124e857815183526124c76020846131be565b92506124d46020836131be565b91506124e1602082612e10565b90506124b0565b905182516020929092036101000a6000190180199091169116179052565b825160009061251583856131be565b111561252057600080fd5b5091016020012090565b60006001600160e01b031982167f124a319c00000000000000000000000000000000000000000000000000000000148061064057506106408260006001600160e01b031982167fa8fa56820000000000000000000000000000000000000000000000000000000014806125c657506001600160e01b031982167f5c98042b00000000000000000000000000000000000000000000000000000000145b8061064057506106408260006001600160e01b031982167fbc1c58d100000000000000000000000000000000000000000000000000000000148061064057506106408260006001600160e01b031982167f3b3b57de00000000000000000000000000000000000000000000000000000000148061266c57506001600160e01b031982167ff1cb7e0600000000000000000000000000000000000000000000000000000000145b8061064057506106408260006001600160e01b031982167f2203ab5600000000000000000000000000000000000000000000000000000000148061064057506106408260006001600160e01b031982167fd700ff3300000000000000000000000000000000000000000000000000000000148061064057506106408260006001600160e01b031982167f4fbf043300000000000000000000000000000000000000000000000000000000148061064057506301ffc9a760e01b6001600160e01b0319831614610640565b50805461274290612e33565b6000825580601f10612752575050565b601f01602090049060005260206000209081019061193d91905b80821115612780576000815560010161276c565b5090565b80356001600160e01b03198116811461279c57600080fd5b919050565b6000602082840312156127b357600080fd5b610ef782612784565b60008083601f8401126127ce57600080fd5b50813567ffffffffffffffff8111156127e657600080fd5b602083019150836020828501011115610d0057600080fd5b60008060006040848603121561281357600080fd5b83359250602084013567ffffffffffffffff81111561283157600080fd5b61283d868287016127bc565b9497909650939450505050565b60008060008060006060868803121561286257600080fd5b85359450602086013567ffffffffffffffff8082111561288157600080fd5b61288d89838a016127bc565b909650945060408801359150808211156128a657600080fd5b506128b3888289016127bc565b969995985093965092949392505050565b600080604083850312156128d757600080fd5b823591506128e760208401612784565b90509250929050565b6000806040838503121561290357600080fd5b50508035926020909101359150565b60005b8381101561292d578181015183820152602001612915565b50506000910152565b6000815180845261294e816020860160208601612912565b601f01601f19169290920160200192915050565b8281526040602082015260006117286040830184612936565b60008060006060848603121561299057600080fd5b505081359360208301359350604090920135919050565b6000602082840312156129b957600080fd5b5035919050565b602081526000610ef76020830184612936565b600080600080606085870312156129e957600080fd5b8435935060208501359250604085013567ffffffffffffffff811115612a0e57600080fd5b612a1a878288016127bc565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b600080600060608486031215612a5157600080fd5b8335925060208401359150604084013567ffffffffffffffff80821115612a7757600080fd5b818601915086601f830112612a8b57600080fd5b813581811115612a9d57612a9d612a26565b604051601f8201601f19908116603f01168101908382118183101715612ac557612ac5612a26565b81604052828152896020848701011115612ade57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6001600160a01b038116811461193d57600080fd5b8035801515811461279c57600080fd5b60008060408385031215612b3857600080fd5b8235612b4381612b00565b91506128e760208401612b15565b600080600060608486031215612b6657600080fd5b833592506020840135612b7881612b00565b9150612b8660408501612b15565b90509250925092565b600080600060608486031215612ba457600080fd5b8335925060208401359150604084013561ffff81168114612bc457600080fd5b809150509250925092565b600080600060608486031215612be457600080fd5b8335612bef81612b00565b9250602084013591506040840135612bc481612b00565b60008083601f840112612c1857600080fd5b50813567ffffffffffffffff811115612c3057600080fd5b6020830191508360208260051b8501011115610d0057600080fd5b60008060208385031215612c5e57600080fd5b823567ffffffffffffffff811115612c7557600080fd5b612c8185828601612c06565b90969095509350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015612ce257603f19888603018452612cd0858351612936565b94509285019290850190600101612cb4565b5092979650505050505050565b600060208284031215612d0157600080fd5b8135610ef781612b00565b60008060408385031215612d1f57600080fd5b823591506020830135612d3181612b00565b809150509250929050565b600080600060408486031215612d5157600080fd5b83359250602084013567ffffffffffffffff811115612d6f57600080fd5b61283d86828701612c06565b600080600060608486031215612d9057600080fd5b83359250612da060208501612784565b91506040840135612bc481612b00565b60008060408385031215612dc357600080fd5b8235612dce81612b00565b91506020830135612d3181612b00565b60008251612df0818460208701612912565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561064057610640612dfa565b8183823760009101908152919050565b600181811c90821680612e4757607f821691505b602082108103612e6757634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561171657600081815260208120601f850160051c81016020861015612e945750805b601f850160051c820191505b81811015612eb357828155600101612ea0565b505050505050565b67ffffffffffffffff831115612ed357612ed3612a26565b612ee783612ee18354612e33565b83612e6d565b6000601f841160018114612f1b5760008515612f035750838201355b600019600387901b1c1916600186901b1783556112e9565b600083815260209020601f19861690835b82811015612f4c5786850135825560209485019460019092019101612f2c565b5086821015612f695760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000612fb8604083018688612f7b565b8281036020840152612fcb818587612f7b565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b602081526000611728602083018486612f7b565b600067ffffffffffffffff80831681810361301d5761301d612dfa565b6001019392505050565b815167ffffffffffffffff81111561304157613041612a26565b6130558161304f8454612e33565b84612e6d565b602080601f83116001811461308a57600084156130725750858301515b600019600386901b1c1916600185901b178555612eb3565b600085815260208120601f198616915b828110156130b95788860151825594840194600190910190840161309a565b50858210156130d75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6040815260006130fa6040830186612936565b828103602084015261310d818587612f7b565b9695505050505050565b60006020828403121561312957600080fd5b8151610ef781612b00565b600061ffff82168061314857613148612dfa565b6000190192915050565b6040815260006131656040830185612936565b905061ffff831660208301529392505050565b600061ffff80831681810361301d5761301d612dfa565b6060815260006131a26060830186612936565b61ffff85166020840152828103604084015261310d8185612936565b8082018082111561064057610640612dfa565b6000808335601e198436030181126131e857600080fd5b83018035915067ffffffffffffffff82111561320357600080fd5b602001915036819003821315610d0057600080fd5b6000808585111561322857600080fd5b8386111561323557600080fd5b5050820193919092039150565b8035602083101561064057600019602084900360031b1b1692915050565b60006001820161327257613272612dfa565b5060010190565b634e487b7160e01b600052600160045260246000fdfea264697066735822122054cd562a646e8cf8d0d2c7644bed8cc9c56090e9e7f4052c23925ed6e9ea015564736f6c63430008110033
RNS.sol
pragma solidity >=0.8.4; interface RNS { // Logged when the owner of a node assigns a new owner to a subnode. event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); // Logged when the owner of a node transfers ownership to a new account. event Transfer(bytes32 indexed node, address owner); // Logged when the resolver for a node changes. event NewResolver(bytes32 indexed node, address resolver); // Logged when the TTL of a node changes event NewTTL(bytes32 indexed node, uint64 ttl); // Logged when an operator is added or removed. event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); function setRecord( bytes32 node, address owner, address resolver, uint64 ttl ) external; function setSubnodeRecord( bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl ) external; function setSubnodeOwner( bytes32 node, bytes32 label, address owner ) external returns (bytes32); function setResolver(bytes32 node, address resolver) external; function setOwner(bytes32 node, address owner) external; function setTTL(bytes32 node, uint64 ttl) external; function setApprovalForAll(address operator, bool approved) external; function owner(bytes32 node) external view returns (address); function resolver(bytes32 node) external view returns (address); function ttl(bytes32 node) external view returns (uint64); function recordExists(bytes32 node) external view returns (bool); function isApprovedForAll( address owner, address operator ) external view returns (bool); }
INameWrapper.sol
//SPDX-License-Identifier: MIT pragma solidity ~0.8.17; import "../registry/RNS.sol"; import "../ethregistrar/IBaseRegistrar.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "./IMetadataService.sol"; import "./INameWrapperUpgrade.sol"; uint32 constant CANNOT_UNWRAP = 1; uint32 constant CANNOT_BURN_FUSES = 2; uint32 constant CANNOT_TRANSFER = 4; uint32 constant CANNOT_SET_RESOLVER = 8; uint32 constant CANNOT_SET_TTL = 16; uint32 constant CANNOT_CREATE_SUBDOMAIN = 32; uint32 constant CANNOT_APPROVE = 64; //uint16 reserved for parent controlled fuses from bit 17 to bit 32 uint32 constant PARENT_CANNOT_CONTROL = 1 << 16; uint32 constant IS_DOT_ETH = 1 << 17; uint32 constant CAN_EXTEND_EXPIRY = 1 << 18; uint32 constant CAN_DO_EVERYTHING = 0; uint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000; // all fuses apart from IS_DOT_ETH uint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF; interface INameWrapper is IERC1155 { event NameWrapped( bytes32 indexed node, bytes name, address owner, uint32 fuses, uint64 expiry ); event NameUnwrapped(bytes32 indexed node, address owner); event FusesSet(bytes32 indexed node, uint32 fuses); event ExpiryExtended(bytes32 indexed node, uint64 expiry); function ens() external view returns (RNS); function registrar() external view returns (IBaseRegistrar); function metadataService() external view returns (IMetadataService); function names(bytes32) external view returns (bytes memory); function name() external view returns (string memory); function upgradeContract() external view returns (INameWrapperUpgrade); function supportsInterface(bytes4 interfaceID) external view returns (bool); function wrap( bytes calldata name, address wrappedOwner, address resolver ) external; function wrapETH2LD( string calldata label, address wrappedOwner, uint16 ownerControlledFuses, address resolver ) external returns (uint64 expires); function registerAndWrapETH2LD( string calldata label, address wrappedOwner, uint256 duration, address resolver, uint16 ownerControlledFuses ) external returns (uint256 registrarExpiry); function renew( uint256 labelHash, uint256 duration ) external returns (uint256 expires); function unwrap(bytes32 node, bytes32 label, address owner) external; function unwrapETH2LD( bytes32 label, address newRegistrant, address newController ) external; function upgrade(bytes calldata name, bytes calldata extraData) external; function setFuses( bytes32 node, uint16 ownerControlledFuses ) external returns (uint32 newFuses); function setChildFuses( bytes32 parentNode, bytes32 labelhash, uint32 fuses, uint64 expiry ) external; function setSubnodeRecord( bytes32 node, string calldata label, address owner, address resolver, uint64 ttl, uint32 fuses, uint64 expiry ) external returns (bytes32); function setRecord( bytes32 node, address owner, address resolver, uint64 ttl ) external; function setSubnodeOwner( bytes32 node, string calldata label, address newOwner, uint32 fuses, uint64 expiry ) external returns (bytes32); function extendExpiry( bytes32 node, bytes32 labelhash, uint64 expiry ) external returns (uint64); function canModifyName( bytes32 node, address addr ) external view returns (bool); function setResolver(bytes32 node, address resolver) external; function setTTL(bytes32 node, uint64 ttl) external; function ownerOf(uint256 id) external view returns (address owner); function approve(address to, uint256 tokenId) external; function getApproved(uint256 tokenId) external view returns (address); function getData( uint256 id ) external view returns (address, uint32, uint64); function setMetadataService(IMetadataService _metadataService) external; function uri(uint256 tokenId) external view returns (string memory); function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external; function allFusesBurned( bytes32 node, uint32 fuseMask ) external view returns (bool); function isWrapped(bytes32) external view returns (bool); function isWrapped(bytes32, bytes32) external view returns (bool); }
RRUtils.sol
pragma solidity ^0.8.4; import "./BytesUtils.sol"; import "@ensdomains/buffer/contracts/Buffer.sol"; /** * @dev RRUtils is a library that provides utilities for parsing DNS resource records. */ library RRUtils { using BytesUtils for *; using Buffer for *; /** * @dev Returns the number of bytes in the DNS name at 'offset' in 'self'. * @param self The byte array to read a name from. * @param offset The offset to start reading at. * @return The length of the DNS name at 'offset', in bytes. */ function nameLength( bytes memory self, uint256 offset ) internal pure returns (uint256) { uint256 idx = offset; while (true) { assert(idx < self.length); uint256 labelLen = self.readUint8(idx); idx += labelLen + 1; if (labelLen == 0) { break; } } return idx - offset; } /** * @dev Returns a DNS format name at the specified offset of self. * @param self The byte array to read a name from. * @param offset The offset to start reading at. * @return ret The name. */ function readName( bytes memory self, uint256 offset ) internal pure returns (bytes memory ret) { uint256 len = nameLength(self, offset); return self.substring(offset, len); } /** * @dev Returns the number of labels in the DNS name at 'offset' in 'self'. * @param self The byte array to read a name from. * @param offset The offset to start reading at. * @return The number of labels in the DNS name at 'offset', in bytes. */ function labelCount( bytes memory self, uint256 offset ) internal pure returns (uint256) { uint256 count = 0; while (true) { assert(offset < self.length); uint256 labelLen = self.readUint8(offset); offset += labelLen + 1; if (labelLen == 0) { break; } count += 1; } return count; } uint256 constant RRSIG_TYPE = 0; uint256 constant RRSIG_ALGORITHM = 2; uint256 constant RRSIG_LABELS = 3; uint256 constant RRSIG_TTL = 4; uint256 constant RRSIG_EXPIRATION = 8; uint256 constant RRSIG_INCEPTION = 12; uint256 constant RRSIG_KEY_TAG = 16; uint256 constant RRSIG_SIGNER_NAME = 18; struct SignedSet { uint16 typeCovered; uint8 algorithm; uint8 labels; uint32 ttl; uint32 expiration; uint32 inception; uint16 keytag; bytes signerName; bytes data; bytes name; } function readSignedSet( bytes memory data ) internal pure returns (SignedSet memory self) { self.typeCovered = data.readUint16(RRSIG_TYPE); self.algorithm = data.readUint8(RRSIG_ALGORITHM); self.labels = data.readUint8(RRSIG_LABELS); self.ttl = data.readUint32(RRSIG_TTL); self.expiration = data.readUint32(RRSIG_EXPIRATION); self.inception = data.readUint32(RRSIG_INCEPTION); self.keytag = data.readUint16(RRSIG_KEY_TAG); self.signerName = readName(data, RRSIG_SIGNER_NAME); self.data = data.substring( RRSIG_SIGNER_NAME + self.signerName.length, data.length - RRSIG_SIGNER_NAME - self.signerName.length ); } function rrs( SignedSet memory rrset ) internal pure returns (RRIterator memory) { return iterateRRs(rrset.data, 0); } /** * @dev An iterator over resource records. */ struct RRIterator { bytes data; uint256 offset; uint16 dnstype; uint16 class; uint32 ttl; uint256 rdataOffset; uint256 nextOffset; } /** * @dev Begins iterating over resource records. * @param self The byte string to read from. * @param offset The offset to start reading at. * @return ret An iterator object. */ function iterateRRs( bytes memory self, uint256 offset ) internal pure returns (RRIterator memory ret) { ret.data = self; ret.nextOffset = offset; next(ret); } /** * @dev Returns true iff there are more RRs to iterate. * @param iter The iterator to check. * @return True iff the iterator has finished. */ function done(RRIterator memory iter) internal pure returns (bool) { return iter.offset >= iter.data.length; } /** * @dev Moves the iterator to the next resource record. * @param iter The iterator to advance. */ function next(RRIterator memory iter) internal pure { iter.offset = iter.nextOffset; if (iter.offset >= iter.data.length) { return; } // Skip the name uint256 off = iter.offset + nameLength(iter.data, iter.offset); // Read type, class, and ttl iter.dnstype = iter.data.readUint16(off); off += 2; iter.class = iter.data.readUint16(off); off += 2; iter.ttl = iter.data.readUint32(off); off += 4; // Read the rdata uint256 rdataLength = iter.data.readUint16(off); off += 2; iter.rdataOffset = off; iter.nextOffset = off + rdataLength; } /** * @dev Returns the name of the current record. * @param iter The iterator. * @return A new bytes object containing the owner name from the RR. */ function name(RRIterator memory iter) internal pure returns (bytes memory) { return iter.data.substring( iter.offset, nameLength(iter.data, iter.offset) ); } /** * @dev Returns the rdata portion of the current record. * @param iter The iterator. * @return A new bytes object containing the RR's RDATA. */ function rdata( RRIterator memory iter ) internal pure returns (bytes memory) { return iter.data.substring( iter.rdataOffset, iter.nextOffset - iter.rdataOffset ); } uint256 constant DNSKEY_FLAGS = 0; uint256 constant DNSKEY_PROTOCOL = 2; uint256 constant DNSKEY_ALGORITHM = 3; uint256 constant DNSKEY_PUBKEY = 4; struct DNSKEY { uint16 flags; uint8 protocol; uint8 algorithm; bytes publicKey; } function readDNSKEY( bytes memory data, uint256 offset, uint256 length ) internal pure returns (DNSKEY memory self) { self.flags = data.readUint16(offset + DNSKEY_FLAGS); self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL); self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM); self.publicKey = data.substring( offset + DNSKEY_PUBKEY, length - DNSKEY_PUBKEY ); } uint256 constant DS_KEY_TAG = 0; uint256 constant DS_ALGORITHM = 2; uint256 constant DS_DIGEST_TYPE = 3; uint256 constant DS_DIGEST = 4; struct DS { uint16 keytag; uint8 algorithm; uint8 digestType; bytes digest; } function readDS( bytes memory data, uint256 offset, uint256 length ) internal pure returns (DS memory self) { self.keytag = data.readUint16(offset + DS_KEY_TAG); self.algorithm = data.readUint8(offset + DS_ALGORITHM); self.digestType = data.readUint8(offset + DS_DIGEST_TYPE); self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST); } function isSubdomainOf( bytes memory self, bytes memory other ) internal pure returns (bool) { uint256 off = 0; uint256 counts = labelCount(self, 0); uint256 othercounts = labelCount(other, 0); while (counts > othercounts) { off = progress(self, off); counts--; } return self.equals(off, other, 0); } function compareNames( bytes memory self, bytes memory other ) internal pure returns (int256) { if (self.equals(other)) { return 0; } uint256 off; uint256 otheroff; uint256 prevoff; uint256 otherprevoff; uint256 counts = labelCount(self, 0); uint256 othercounts = labelCount(other, 0); // Keep removing labels from the front of the name until both names are equal length while (counts > othercounts) { prevoff = off; off = progress(self, off); counts--; } while (othercounts > counts) { otherprevoff = otheroff; otheroff = progress(other, otheroff); othercounts--; } // Compare the last nonequal labels to each other while (counts > 0 && !self.equals(off, other, otheroff)) { prevoff = off; off = progress(self, off); otherprevoff = otheroff; otheroff = progress(other, otheroff); counts -= 1; } if (off == 0) { return -1; } if (otheroff == 0) { return 1; } return self.compare( prevoff + 1, self.readUint8(prevoff), other, otherprevoff + 1, other.readUint8(otherprevoff) ); } /** * @dev Compares two serial numbers using RFC1982 serial number math. */ function serialNumberGte( uint32 i1, uint32 i2 ) internal pure returns (bool) { unchecked { return int32(i1) - int32(i2) >= 0; } } function progress( bytes memory body, uint256 off ) internal pure returns (uint256) { return off + 1 + body.readUint8(off); } /** * @dev Computes the keytag for a chunk of data. * @param data The data to compute a keytag for. * @return The computed key tag. */ function computeKeytag(bytes memory data) internal pure returns (uint16) { /* This function probably deserves some explanation. * The DNSSEC keytag function is a checksum that relies on summing up individual bytes * from the input string, with some mild bitshifting. Here's a Naive solidity implementation: * * function computeKeytag(bytes memory data) internal pure returns (uint16) { * uint ac; * for (uint i = 0; i < data.length; i++) { * ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i); * } * return uint16(ac + (ac >> 16)); * } * * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations; * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's * large words work in our favour. * * The code below works by treating the input as a series of 256 bit words. It first masks out * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`. * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're * effectively summing 16 different numbers with each EVM ADD opcode. * * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together. * It does this using the same trick - mask out every other value, shift to align them, add them together. * After the first addition on both accumulators, there's enough room to add the two accumulators together, * and the remaining sums can be done just on ac1. */ unchecked { require(data.length <= 8192, "Long keys not permitted"); uint256 ac1; uint256 ac2; for (uint256 i = 0; i < data.length + 31; i += 32) { uint256 word; assembly { word := mload(add(add(data, 32), i)) } if (i + 32 > data.length) { uint256 unused = 256 - (data.length - i) * 8; word = (word >> unused) << unused; } ac1 += (word & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8; ac2 += (word & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF); } ac1 = (ac1 & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) + ((ac1 & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16); ac2 = (ac2 & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) + ((ac2 & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16); ac1 = (ac1 << 8) + ac2; ac1 = (ac1 & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) + ((ac1 & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32); ac1 = (ac1 & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) + ((ac1 & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64); ac1 = (ac1 & 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + (ac1 >> 128); ac1 += (ac1 >> 16) & 0xFFFF; return uint16(ac1); } } }
ResolverBase.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "./profiles/IVersionableResolver.sol"; abstract contract ResolverBase is ERC165, IVersionableResolver { mapping(bytes32 => uint64) public recordVersions; function isAuthorised(bytes32 node) internal view virtual returns (bool); modifier authorised(bytes32 node) { require(isAuthorised(node)); _; } /** * Increments the record version associated with an RNS node. * May only be called by the owner of that node in the RNS registry. * @param node The node to update. */ function clearRecords(bytes32 node) public virtual authorised(node) { recordVersions[node]++; emit VersionChanged(node, recordVersions[node]); } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IVersionableResolver).interfaceId || super.supportsInterface(interfaceID); } }
Multicallable.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./IMulticallable.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; abstract contract Multicallable is IMulticallable, ERC165 { function _multicall( bytes32 nodehash, bytes[] calldata data ) internal returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { if (nodehash != bytes32(0)) { bytes32 txNamehash = bytes32(data[i][4:36]); require( txNamehash == nodehash, "multicall: All records must have a matching namehash" ); } (bool success, bytes memory result) = address(this).delegatecall( data[i] ); require(success); results[i] = result; } return results; } // This function provides an extra security check when called // from priviledged contracts (such as EthRegistrarController) // that can set records on behalf of the node owners function multicallWithNodeCheck( bytes32 nodehash, bytes[] calldata data ) external returns (bytes[] memory results) { return _multicall(nodehash, data); } function multicall( bytes[] calldata data ) public override returns (bytes[] memory results) { return _multicall(bytes32(0), data); } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IMulticallable).interfaceId || super.supportsInterface(interfaceID); } }
BytesUtils.sol
pragma solidity ^0.8.4; library BytesUtils { error OffsetOutOfBoundsError(uint256 offset, uint256 length); /* * @dev Returns the keccak-256 hash of a byte range. * @param self The byte string to hash. * @param offset The position to start hashing at. * @param len The number of bytes to hash. * @return The hash of the byte range. */ function keccak( bytes memory self, uint256 offset, uint256 len ) internal pure returns (bytes32 ret) { require(offset + len <= self.length); assembly { ret := keccak256(add(add(self, 32), offset), len) } } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two bytes are equal. * @param self The first bytes to compare. * @param other The second bytes to compare. * @return The result of the comparison. */ function compare( bytes memory self, bytes memory other ) internal pure returns (int256) { return compare(self, 0, self.length, other, 0, other.length); } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two bytes are equal. Comparison is done per-rune, * on unicode codepoints. * @param self The first bytes to compare. * @param offset The offset of self. * @param len The length of self. * @param other The second bytes to compare. * @param otheroffset The offset of the other string. * @param otherlen The length of the other string. * @return The result of the comparison. */ function compare( bytes memory self, uint256 offset, uint256 len, bytes memory other, uint256 otheroffset, uint256 otherlen ) internal pure returns (int256) { if (offset + len > self.length) { revert OffsetOutOfBoundsError(offset + len, self.length); } if (otheroffset + otherlen > other.length) { revert OffsetOutOfBoundsError(otheroffset + otherlen, other.length); } uint256 shortest = len; if (otherlen < len) shortest = otherlen; uint256 selfptr; uint256 otherptr; assembly { selfptr := add(self, add(offset, 32)) otherptr := add(other, add(otheroffset, 32)) } for (uint256 idx = 0; idx < shortest; idx += 32) { uint256 a; uint256 b; assembly { a := mload(selfptr) b := mload(otherptr) } if (a != b) { // Mask out irrelevant bytes and check again uint256 mask; if (shortest - idx >= 32) { mask = type(uint256).max; } else { mask = ~(2 ** (8 * (idx + 32 - shortest)) - 1); } int256 diff = int256(a & mask) - int256(b & mask); if (diff != 0) return diff; } selfptr += 32; otherptr += 32; } return int256(len) - int256(otherlen); } /* * @dev Returns true if the two byte ranges are equal. * @param self The first byte range to compare. * @param offset The offset into the first byte range. * @param other The second byte range to compare. * @param otherOffset The offset into the second byte range. * @param len The number of bytes to compare * @return True if the byte ranges are equal, false otherwise. */ function equals( bytes memory self, uint256 offset, bytes memory other, uint256 otherOffset, uint256 len ) internal pure returns (bool) { return keccak(self, offset, len) == keccak(other, otherOffset, len); } /* * @dev Returns true if the two byte ranges are equal with offsets. * @param self The first byte range to compare. * @param offset The offset into the first byte range. * @param other The second byte range to compare. * @param otherOffset The offset into the second byte range. * @return True if the byte ranges are equal, false otherwise. */ function equals( bytes memory self, uint256 offset, bytes memory other, uint256 otherOffset ) internal pure returns (bool) { return keccak(self, offset, self.length - offset) == keccak(other, otherOffset, other.length - otherOffset); } /* * @dev Compares a range of 'self' to all of 'other' and returns True iff * they are equal. * @param self The first byte range to compare. * @param offset The offset into the first byte range. * @param other The second byte range to compare. * @return True if the byte ranges are equal, false otherwise. */ function equals( bytes memory self, uint256 offset, bytes memory other ) internal pure returns (bool) { return self.length == offset + other.length && equals(self, offset, other, 0, other.length); } /* * @dev Returns true if the two byte ranges are equal. * @param self The first byte range to compare. * @param other The second byte range to compare. * @return True if the byte ranges are equal, false otherwise. */ function equals( bytes memory self, bytes memory other ) internal pure returns (bool) { return self.length == other.length && equals(self, 0, other, 0, self.length); } /* * @dev Returns the 8-bit number at the specified index of self. * @param self The byte string. * @param idx The index into the bytes * @return The specified 8 bits of the string, interpreted as an integer. */ function readUint8( bytes memory self, uint256 idx ) internal pure returns (uint8 ret) { return uint8(self[idx]); } /* * @dev Returns the 16-bit number at the specified index of self. * @param self The byte string. * @param idx The index into the bytes * @return The specified 16 bits of the string, interpreted as an integer. */ function readUint16( bytes memory self, uint256 idx ) internal pure returns (uint16 ret) { require(idx + 2 <= self.length); assembly { ret := and(mload(add(add(self, 2), idx)), 0xFFFF) } } /* * @dev Returns the 32-bit number at the specified index of self. * @param self The byte string. * @param idx The index into the bytes * @return The specified 32 bits of the string, interpreted as an integer. */ function readUint32( bytes memory self, uint256 idx ) internal pure returns (uint32 ret) { require(idx + 4 <= self.length); assembly { ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF) } } /* * @dev Returns the 32 byte value at the specified index of self. * @param self The byte string. * @param idx The index into the bytes * @return The specified 32 bytes of the string. */ function readBytes32( bytes memory self, uint256 idx ) internal pure returns (bytes32 ret) { require(idx + 32 <= self.length); assembly { ret := mload(add(add(self, 32), idx)) } } /* * @dev Returns the 32 byte value at the specified index of self. * @param self The byte string. * @param idx The index into the bytes * @return The specified 32 bytes of the string. */ function readBytes20( bytes memory self, uint256 idx ) internal pure returns (bytes20 ret) { require(idx + 20 <= self.length); assembly { ret := and( mload(add(add(self, 32), idx)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000 ) } } /* * @dev Returns the n byte value at the specified index of self. * @param self The byte string. * @param idx The index into the bytes. * @param len The number of bytes. * @return The specified 32 bytes of the string. */ function readBytesN( bytes memory self, uint256 idx, uint256 len ) internal pure returns (bytes32 ret) { require(len <= 32); require(idx + len <= self.length); assembly { let mask := not(sub(exp(256, sub(32, len)), 1)) ret := and(mload(add(add(self, 32), idx)), mask) } } function memcpy(uint256 dest, uint256 src, uint256 len) private pure { // Copy word-length chunks while possible for (; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes unchecked { uint256 mask = (256 ** (32 - len)) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } } /* * @dev Copies a substring into a new byte string. * @param self The byte string to copy from. * @param offset The offset to start copying at. * @param len The number of bytes to copy. */ function substring( bytes memory self, uint256 offset, uint256 len ) internal pure returns (bytes memory) { require(offset + len <= self.length); bytes memory ret = new bytes(len); uint256 dest; uint256 src; assembly { dest := add(ret, 32) src := add(add(self, 32), offset) } memcpy(dest, src, len); return ret; } // Maps characters from 0x30 to 0x7A to their base32 values. // 0xFF represents invalid characters in that range. bytes constant base32HexTable = hex"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"; /** * @dev Decodes unpadded base32 data of up to one word in length. * @param self The data to decode. * @param off Offset into the string to start at. * @param len Number of characters to decode. * @return The decoded data, left aligned. */ function base32HexDecodeWord( bytes memory self, uint256 off, uint256 len ) internal pure returns (bytes32) { require(len <= 52); uint256 ret = 0; uint8 decoded; for (uint256 i = 0; i < len; i++) { bytes1 char = self[off + i]; require(char >= 0x30 && char <= 0x7A); decoded = uint8(base32HexTable[uint256(uint8(char)) - 0x30]); require(decoded <= 0x20); if (i == len - 1) { break; } ret = (ret << 5) | decoded; } uint256 bitlen = len * 5; if (len % 8 == 0) { // Multiple of 8 characters, no padding ret = (ret << 5) | decoded; } else if (len % 8 == 2) { // Two extra characters - 1 byte ret = (ret << 3) | (decoded >> 2); bitlen -= 2; } else if (len % 8 == 4) { // Four extra characters - 2 bytes ret = (ret << 1) | (decoded >> 4); bitlen -= 4; } else if (len % 8 == 5) { // Five extra characters - 3 bytes ret = (ret << 4) | (decoded >> 1); bitlen -= 1; } else if (len % 8 == 7) { // Seven extra characters - 4 bytes ret = (ret << 2) | (decoded >> 3); bitlen -= 3; } else { revert(); } return bytes32(ret << (256 - bitlen)); } /** * @dev Finds the first occurrence of the byte `needle` in `self`. * @param self The string to search * @param off The offset to start searching at * @param len The number of bytes to search * @param needle The byte to search for * @return The offset of `needle` in `self`, or 2**256-1 if it was not found. */ function find( bytes memory self, uint256 off, uint256 len, bytes1 needle ) internal pure returns (uint256) { for (uint256 idx = off; idx < off + len; idx++) { if (self[idx] == needle) { return idx; } } return type(uint256).max; } }
IMulticallable.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; interface IMulticallable { function multicall( bytes[] calldata data ) external returns (bytes[] memory results); function multicallWithNodeCheck( bytes32, bytes[] calldata data ) external returns (bytes[] memory results); }
PublicResolver.sol
//SPDX-License-Identifier: MIT pragma solidity >=0.8.17 <0.9.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "../registry/RNS.sol"; import "./profiles/ABIResolver.sol"; import "./profiles/AddrResolver.sol"; import "./profiles/ContentHashResolver.sol"; import "./profiles/DNSResolver.sol"; import "./profiles/InterfaceResolver.sol"; import "./profiles/NameResolver.sol"; import "./profiles/PubkeyResolver.sol"; import "./profiles/TextResolver.sol"; import "./Multicallable.sol"; import {ReverseClaimer} from "../reverseRegistrar/ReverseClaimer.sol"; import {INameWrapper} from "../wrapper/INameWrapper.sol"; /** * A simple resolver anyone can use; only allows the owner of a node to set its * address. */ contract PublicResolver is Ownable, Multicallable, ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver, ReverseClaimer { RNS immutable ens; INameWrapper immutable nameWrapper; address public trustedETHController; address immutable trustedReverseRegistrar; /** * A mapping of operators. An address that is authorised for an address * may make any changes to the name that the owner could, but may not update * the set of authorisations. * (owner, operator) => approved */ mapping(address => mapping(address => bool)) private _operatorApprovals; /** * A mapping of delegates. A delegate that is authorised by an owner * for a name may make changes to the name's resolver, but may not update * the set of token approvals. * (owner, name, delegate) => approved */ mapping(address => mapping(bytes32 => mapping(address => bool))) private _tokenApprovals; // Logged when an operator is added or removed. event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); event SetETHController(address controller); // Logged when a delegate is approved or an approval is revoked. event Approved( address owner, bytes32 indexed node, address indexed delegate, bool indexed approved ); constructor( RNS _ens, INameWrapper wrapperAddress, address _trustedETHController, address _trustedReverseRegistrar ) ReverseClaimer(_ens, msg.sender) { ens = _ens; nameWrapper = wrapperAddress; trustedETHController = _trustedETHController; trustedReverseRegistrar = _trustedReverseRegistrar; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) external { require( msg.sender != operator, "ERC1155: setting approval status for self" ); _operatorApprovals[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll( address account, address operator ) public view returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev Approve a delegate to be able to updated records on a node. */ function approve(bytes32 node, address delegate, bool approved) external { require(msg.sender != delegate, "Setting delegate status for self"); _tokenApprovals[msg.sender][node][delegate] = approved; emit Approved(msg.sender, node, delegate, approved); } /** * @dev Check to see if the delegate has been approved by the owner for the node. */ function isApprovedFor( address owner, bytes32 node, address delegate ) public view returns (bool) { return _tokenApprovals[owner][node][delegate]; } function isAuthorised(bytes32 node) internal view override returns (bool) { if ( msg.sender == trustedETHController || msg.sender == trustedReverseRegistrar ) { return true; } address owner = ens.owner(node); if (owner == address(nameWrapper)) { owner = nameWrapper.ownerOf(uint256(node)); } return owner == msg.sender || isApprovedForAll(owner, msg.sender) || isApprovedFor(owner, node, msg.sender); } function supportsInterface( bytes4 interfaceID ) public view override( Multicallable, ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver ) returns (bool) { return super.supportsInterface(interfaceID); } function setETHController(address _controller) external onlyOwner { trustedETHController = _controller; emit SetETHController(_controller); } }
IMetadataService.sol
//SPDX-License-Identifier: MIT pragma solidity ~0.8.17; interface IMetadataService { function uri(uint256) external view returns (string memory); }
Buffer.sol
// SPDX-License-Identifier: BSD-2-Clause pragma solidity ^0.8.4; /** * @dev A library for working with mutable byte buffers in Solidity. * * Byte buffers are mutable and expandable, and provide a variety of primitives * for appending to them. At any time you can fetch a bytes object containing the * current contents of the buffer. The bytes object should not be stored between * operations, as it may change due to resizing of the buffer. */ library Buffer { /** * @dev Represents a mutable buffer. Buffers have a current value (buf) and * a capacity. The capacity may be longer than the current value, in * which case it can be extended without the need to allocate more memory. */ struct buffer { bytes buf; uint capacity; } /** * @dev Initializes a buffer with an initial capacity. * @param buf The buffer to initialize. * @param capacity The number of bytes of space to allocate the buffer. * @return The buffer, for chaining. */ function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) { if (capacity % 32 != 0) { capacity += 32 - (capacity % 32); } // Allocate space for the buffer data buf.capacity = capacity; assembly { let ptr := mload(0x40) mstore(buf, ptr) mstore(ptr, 0) let fpm := add(32, add(ptr, capacity)) if lt(fpm, ptr) { revert(0, 0) } mstore(0x40, fpm) } return buf; } /** * @dev Initializes a new buffer from an existing bytes object. * Changes to the buffer may mutate the original value. * @param b The bytes object to initialize the buffer with. * @return A new buffer. */ function fromBytes(bytes memory b) internal pure returns(buffer memory) { buffer memory buf; buf.buf = b; buf.capacity = b.length; return buf; } function resize(buffer memory buf, uint capacity) private pure { bytes memory oldbuf = buf.buf; init(buf, capacity); append(buf, oldbuf); } /** * @dev Sets buffer length to 0. * @param buf The buffer to truncate. * @return The original buffer, for chaining.. */ function truncate(buffer memory buf) internal pure returns (buffer memory) { assembly { let bufptr := mload(buf) mstore(bufptr, 0) } return buf; } /** * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @param len The number of bytes to copy. * @return The original buffer, for chaining. */ function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) { require(len <= data.length); uint off = buf.buf.length; uint newCapacity = off + len; if (newCapacity > buf.capacity) { resize(buf, newCapacity * 2); } uint dest; uint src; assembly { // Memory address of the buffer data let bufptr := mload(buf) // Length of existing buffer data let buflen := mload(bufptr) // Start address = buffer address + offset + sizeof(buffer length) dest := add(add(bufptr, 32), off) // Update buffer length if we're extending it if gt(newCapacity, buflen) { mstore(bufptr, newCapacity) } src := add(data, 32) } // Copy word-length chunks while possible for (; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes unchecked { uint mask = (256 ** (32 - len)) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } return buf; } /** * @dev Appends a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { return append(buf, data, data.length); } /** * @dev Appends a byte to the buffer. Resizes if doing so would exceed the * capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) { uint off = buf.buf.length; uint offPlusOne = off + 1; if (off >= buf.capacity) { resize(buf, offPlusOne * 2); } assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + sizeof(buffer length) + off let dest := add(add(bufptr, off), 32) mstore8(dest, data) // Update buffer length if we extended it if gt(offPlusOne, mload(bufptr)) { mstore(bufptr, offPlusOne) } } return buf; } /** * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would * exceed the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @param len The number of bytes to write (left-aligned). * @return The original buffer, for chaining. */ function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) { uint off = buf.buf.length; uint newCapacity = len + off; if (newCapacity > buf.capacity) { resize(buf, newCapacity * 2); } unchecked { uint mask = (256 ** len) - 1; // Right-align data data = data >> (8 * (32 - len)); assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + sizeof(buffer length) + newCapacity let dest := add(bufptr, newCapacity) mstore(dest, or(and(mload(dest), not(mask)), data)) // Update buffer length if we extended it if gt(newCapacity, mload(bufptr)) { mstore(bufptr, newCapacity) } } } return buf; } /** * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chhaining. */ function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { return append(buf, bytes32(data), 20); } /** * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { return append(buf, data, 32); } /** * @dev Appends a byte to the end of the buffer. Resizes if doing so would * exceed the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @param len The number of bytes to write (right-aligned). * @return The original buffer. */ function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { uint off = buf.buf.length; uint newCapacity = len + off; if (newCapacity > buf.capacity) { resize(buf, newCapacity * 2); } uint mask = (256 ** len) - 1; assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + sizeof(buffer length) + newCapacity let dest := add(bufptr, newCapacity) mstore(dest, or(and(mload(dest), not(mask)), data)) // Update buffer length if we extended it if gt(newCapacity, mload(bufptr)) { mstore(bufptr, newCapacity) } } return buf; } }
Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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; } }
IBaseRegistrar.sol
import "../registry/RNS.sol"; import "./IBaseRegistrar.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; interface IBaseRegistrar is IERC721 { event ControllerAdded(address indexed controller); event ControllerRemoved(address indexed controller); event NameMigrated( uint256 indexed id, address indexed owner, uint256 expires ); event NameRegistered( uint256 indexed id, address indexed owner, uint256 expires ); event NameRenewed(uint256 indexed id, uint256 expires); // Authorises a controller, who can register and renew domains. function addController(address controller) external; // Revoke controller permission for an address. function removeController(address controller) external; // Set the resolver for the TLD this registrar manages. function setResolver(address resolver) external; // Returns the expiration timestamp of the specified label hash. function nameExpires(uint256 id) external view returns (uint256); // Returns true if the specified name is available for registration. function available(uint256 id) external view returns (bool); /** * @dev Register a name. */ function register( uint256 id, address owner, uint256 duration ) external returns (uint256); function renew(uint256 id, uint256 duration) external returns (uint256); /** * @dev Reclaim ownership of a name in RNS, if you own it in the registrar. */ function reclaim(uint256 id, address owner) external; }
INameWrapperUpgrade.sol
//SPDX-License-Identifier: MIT pragma solidity ~0.8.17; interface INameWrapperUpgrade { function wrapFromUpgrade( bytes calldata name, address wrappedOwner, uint32 fuses, uint64 expiry, address approved, bytes calldata extraData ) external; }
Ownable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
ABIResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "./IABIResolver.sol"; import "../ResolverBase.sol"; abstract contract ABIResolver is IABIResolver, ResolverBase { mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_abis; /** * Sets the ABI associated with an RNS node. * Nodes may have one ABI of each content type. To remove an ABI, set it to * the empty string. * @param node The node to update. * @param contentType The content type of the ABI * @param data The ABI data. */ function setABI( bytes32 node, uint256 contentType, bytes calldata data ) external virtual authorised(node) { // Content types must be powers of 2 require(((contentType - 1) & contentType) == 0); versionable_abis[recordVersions[node]][node][contentType] = data; emit ABIChanged(node, contentType); } /** * Returns the ABI associated with an RNS node. * Defined in EIP205. * @param node The RNS node to query * @param contentTypes A bitwise OR of the ABI formats accepted by the caller. * @return contentType The content type of the return value * @return data The ABI data */ function ABI( bytes32 node, uint256 contentTypes ) external view virtual override returns (uint256, bytes memory) { mapping(uint256 => bytes) storage abiset = versionable_abis[ recordVersions[node] ][node]; for ( uint256 contentType = 1; contentType <= contentTypes; contentType <<= 1 ) { if ( (contentType & contentTypes) != 0 && abiset[contentType].length > 0 ) { return (contentType, abiset[contentType]); } } return (0, bytes("")); } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IABIResolver).interfaceId || super.supportsInterface(interfaceID); } }
DNSResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "../ResolverBase.sol"; import "../../dnssec-oracle/RRUtils.sol"; import "./IDNSRecordResolver.sol"; import "./IDNSZoneResolver.sol"; abstract contract DNSResolver is IDNSRecordResolver, IDNSZoneResolver, ResolverBase { using RRUtils for *; using BytesUtils for bytes; // Zone hashes for the domains. // A zone hash is an EIP-1577 content hash in binary format that should point to a // resource containing a single zonefile. // node => contenthash mapping(uint64 => mapping(bytes32 => bytes)) private versionable_zonehashes; // The records themselves. Stored as binary RRSETs // node => version => name => resource => data mapping(uint64 => mapping(bytes32 => mapping(bytes32 => mapping(uint16 => bytes)))) private versionable_records; // Count of number of entries for a given name. Required for DNS resolvers // when resolving wildcards. // node => version => name => number of records mapping(uint64 => mapping(bytes32 => mapping(bytes32 => uint16))) private versionable_nameEntriesCount; /** * Set one or more DNS records. Records are supplied in wire-format. * Records with the same node/name/resource must be supplied one after the * other to ensure the data is updated correctly. For example, if the data * was supplied: * a.example.com IN A 1.2.3.4 * a.example.com IN A 5.6.7.8 * www.example.com IN CNAME a.example.com. * then this would store the two A records for a.example.com correctly as a * single RRSET, however if the data was supplied: * a.example.com IN A 1.2.3.4 * www.example.com IN CNAME a.example.com. * a.example.com IN A 5.6.7.8 * then this would store the first A record, the CNAME, then the second A * record which would overwrite the first. * * @param node the namehash of the node for which to set the records * @param data the DNS wire format records to set */ function setDNSRecords( bytes32 node, bytes calldata data ) external virtual authorised(node) { uint16 resource = 0; uint256 offset = 0; bytes memory name; bytes memory value; bytes32 nameHash; uint64 version = recordVersions[node]; // Iterate over the data to add the resource records for ( RRUtils.RRIterator memory iter = data.iterateRRs(0); !iter.done(); iter.next() ) { if (resource == 0) { resource = iter.dnstype; name = iter.name(); nameHash = keccak256(abi.encodePacked(name)); value = bytes(iter.rdata()); } else { bytes memory newName = iter.name(); if (resource != iter.dnstype || !name.equals(newName)) { setDNSRRSet( node, name, resource, data, offset, iter.offset - offset, value.length == 0, version ); resource = iter.dnstype; offset = iter.offset; name = newName; nameHash = keccak256(name); value = bytes(iter.rdata()); } } } if (name.length > 0) { setDNSRRSet( node, name, resource, data, offset, data.length - offset, value.length == 0, version ); } } /** * Obtain a DNS record. * @param node the namehash of the node for which to fetch the record * @param name the keccak-256 hash of the fully-qualified name for which to fetch the record * @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types * @return the DNS record in wire format if present, otherwise empty */ function dnsRecord( bytes32 node, bytes32 name, uint16 resource ) public view virtual override returns (bytes memory) { return versionable_records[recordVersions[node]][node][name][resource]; } /** * Check if a given node has records. * @param node the namehash of the node for which to check the records * @param name the namehash of the node for which to check the records */ function hasDNSRecords( bytes32 node, bytes32 name ) public view virtual returns (bool) { return (versionable_nameEntriesCount[recordVersions[node]][node][ name ] != 0); } /** * setZonehash sets the hash for the zone. * May only be called by the owner of that node in the RNS registry. * @param node The node to update. * @param hash The zonehash to set */ function setZonehash( bytes32 node, bytes calldata hash ) external virtual authorised(node) { uint64 currentRecordVersion = recordVersions[node]; bytes memory oldhash = versionable_zonehashes[currentRecordVersion][ node ]; versionable_zonehashes[currentRecordVersion][node] = hash; emit DNSZonehashChanged(node, oldhash, hash); } /** * zonehash obtains the hash for the zone. * @param node The RNS node to query. * @return The associated contenthash. */ function zonehash( bytes32 node ) external view virtual override returns (bytes memory) { return versionable_zonehashes[recordVersions[node]][node]; } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IDNSRecordResolver).interfaceId || interfaceID == type(IDNSZoneResolver).interfaceId || super.supportsInterface(interfaceID); } function setDNSRRSet( bytes32 node, bytes memory name, uint16 resource, bytes memory data, uint256 offset, uint256 size, bool deleteRecord, uint64 version ) private { bytes32 nameHash = keccak256(name); bytes memory rrData = data.substring(offset, size); if (deleteRecord) { if ( versionable_records[version][node][nameHash][resource].length != 0 ) { versionable_nameEntriesCount[version][node][nameHash]--; } delete (versionable_records[version][node][nameHash][resource]); emit DNSRecordDeleted(node, name, resource); } else { if ( versionable_records[version][node][nameHash][resource].length == 0 ) { versionable_nameEntriesCount[version][node][nameHash]++; } versionable_records[version][node][nameHash][resource] = rrData; emit DNSRecordChanged(node, name, resource, rrData); } } }
AddrResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "../ResolverBase.sol"; import "./IAddrResolver.sol"; import "./IAddressResolver.sol"; abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase { uint256 private constant COIN_TYPE_ETH = 60; mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_addresses; /** * Sets the address associated with an RNS node. * May only be called by the owner of that node in the RNS registry. * @param node The node to update. * @param a The address to set. */ function setAddr( bytes32 node, address a ) external virtual authorised(node) { setAddr(node, COIN_TYPE_ETH, addressToBytes(a)); } /** * Returns the address associated with an RNS node. * @param node The RNS node to query. * @return The associated address. */ function addr( bytes32 node ) public view virtual override returns (address payable) { bytes memory a = addr(node, COIN_TYPE_ETH); if (a.length == 0) { return payable(0); } return bytesToAddress(a); } function setAddr( bytes32 node, uint256 coinType, bytes memory a ) public virtual authorised(node) { emit AddressChanged(node, coinType, a); if (coinType == COIN_TYPE_ETH) { emit AddrChanged(node, bytesToAddress(a)); } versionable_addresses[recordVersions[node]][node][coinType] = a; } function addr( bytes32 node, uint256 coinType ) public view virtual override returns (bytes memory) { return versionable_addresses[recordVersions[node]][node][coinType]; } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IAddrResolver).interfaceId || interfaceID == type(IAddressResolver).interfaceId || super.supportsInterface(interfaceID); } function bytesToAddress( bytes memory b ) internal pure returns (address payable a) { require(b.length == 20); assembly { a := div(mload(add(b, 32)), exp(256, 12)) } } function addressToBytes(address a) internal pure returns (bytes memory b) { b = new bytes(20); assembly { mstore(add(b, 32), mul(a, exp(256, 12))) } } }
IABIResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface IABIResolver { event ABIChanged(bytes32 indexed node, uint256 indexed contentType); /** * Returns the ABI associated with an RNS node. * Defined in EIP205. * @param node The RNS node to query * @param contentTypes A bitwise OR of the ABI formats accepted by the caller. * @return contentType The content type of the return value * @return data The ABI data */ function ABI( bytes32 node, uint256 contentTypes ) external view returns (uint256, bytes memory); }
NameResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "../ResolverBase.sol"; import "./INameResolver.sol"; abstract contract NameResolver is INameResolver, ResolverBase { mapping(uint64 => mapping(bytes32 => string)) versionable_names; /** * Sets the name associated with an RNS node, for reverse records. * May only be called by the owner of that node in the RNS registry. * @param node The node to update. */ function setName( bytes32 node, string calldata newName ) external virtual authorised(node) { versionable_names[recordVersions[node]][node] = newName; emit NameChanged(node, newName); } /** * Returns the name associated with an RNS node, for reverse records. * Defined in EIP181. * @param node The RNS node to query. * @return The associated name. */ function name( bytes32 node ) external view virtual override returns (string memory) { return versionable_names[recordVersions[node]][node]; } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(INameResolver).interfaceId || super.supportsInterface(interfaceID); } }
TextResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "../ResolverBase.sol"; import "./ITextResolver.sol"; abstract contract TextResolver is ITextResolver, ResolverBase { mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts; /** * Sets the text data associated with an RNS node and key. * May only be called by the owner of that node in the RNS registry. * @param node The node to update. * @param key The key to set. * @param value The text data value to set. */ function setText( bytes32 node, string calldata key, string calldata value ) external virtual authorised(node) { versionable_texts[recordVersions[node]][node][key] = value; emit TextChanged(node, key, key, value); } /** * Returns the text data associated with an RNS node and key. * @param node The RNS node to query. * @param key The text data key to query. * @return The associated text data. */ function text( bytes32 node, string calldata key ) external view virtual override returns (string memory) { return versionable_texts[recordVersions[node]][node][key]; } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(ITextResolver).interfaceId || super.supportsInterface(interfaceID); } }
ReverseClaimer.sol
//SPDX-License-Identifier: MIT pragma solidity >=0.8.17 <0.9.0; import {RNS} from "../registry/RNS.sol"; import {IReverseRegistrar} from "../reverseRegistrar/IReverseRegistrar.sol"; contract ReverseClaimer { bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; constructor(RNS ens, address claimant) { IReverseRegistrar reverseRegistrar = IReverseRegistrar( ens.owner(ADDR_REVERSE_NODE) ); reverseRegistrar.claim(claimant); } }
IAddrResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; /** * Interface for the legacy (ETH-only) addr function. */ interface IAddrResolver { event AddrChanged(bytes32 indexed node, address a); /** * Returns the address associated with an RNS node. * @param node The RNS node to query. * @return The associated address. */ function addr(bytes32 node) external view returns (address payable); }
INameResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface INameResolver { event NameChanged(bytes32 indexed node, string name); /** * Returns the name associated with an RNS node, for reverse records. * Defined in EIP181. * @param node The RNS node to query. * @return The associated name. */ function name(bytes32 node) external view returns (string memory); }
ITextResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface ITextResolver { event TextChanged( bytes32 indexed node, string indexed indexedKey, string key, string value ); /** * Returns the text data associated with an RNS node and key. * @param node The RNS node to query. * @param key The text data key to query. * @return The associated text data. */ function text( bytes32 node, string calldata key ) external view returns (string memory); }
PubkeyResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "../ResolverBase.sol"; import "./IPubkeyResolver.sol"; abstract contract PubkeyResolver is IPubkeyResolver, ResolverBase { struct PublicKey { bytes32 x; bytes32 y; } mapping(uint64 => mapping(bytes32 => PublicKey)) versionable_pubkeys; /** * Sets the SECP256k1 public key associated with an RNS node. * @param node The RNS node to query * @param x the X coordinate of the curve point for the public key. * @param y the Y coordinate of the curve point for the public key. */ function setPubkey( bytes32 node, bytes32 x, bytes32 y ) external virtual authorised(node) { versionable_pubkeys[recordVersions[node]][node] = PublicKey(x, y); emit PubkeyChanged(node, x, y); } /** * Returns the SECP256k1 public key associated with an RNS node. * Defined in EIP 619. * @param node The RNS node to query * @return x The X coordinate of the curve point for the public key. * @return y The Y coordinate of the curve point for the public key. */ function pubkey( bytes32 node ) external view virtual override returns (bytes32 x, bytes32 y) { uint64 currentRecordVersion = recordVersions[node]; return ( versionable_pubkeys[currentRecordVersion][node].x, versionable_pubkeys[currentRecordVersion][node].y ); } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IPubkeyResolver).interfaceId || super.supportsInterface(interfaceID); } }
IERC721.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
IPubkeyResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface IPubkeyResolver { event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y); /** * Returns the SECP256k1 public key associated with an RNS node. * Defined in EIP 619. * @param node The RNS node to query * @return x The X coordinate of the curve point for the public key. * @return y The Y coordinate of the curve point for the public key. */ function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y); }
IReverseRegistrar.sol
pragma solidity >=0.8.4; interface IReverseRegistrar { function setDefaultResolver(address resolver) external; function claim(address owner) external returns (bytes32); function claimForAddr( address addr, address owner, address resolver ) external returns (bytes32); function claimWithResolver( address owner, address resolver ) external returns (bytes32); function setName(string memory name) external returns (bytes32); function setNameForAddr( address addr, address owner, address resolver, string memory name ) external returns (bytes32); function node(address addr) external pure returns (bytes32); }
IAddressResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; /** * Interface for the new (multicoin) addr function. */ interface IAddressResolver { event AddressChanged( bytes32 indexed node, uint256 coinType, bytes newAddress ); function addr( bytes32 node, uint256 coinType ) external view returns (bytes memory); }
IDNSZoneResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface IDNSZoneResolver { // DNSZonehashChanged is emitted whenever a given node's zone hash is updated. event DNSZonehashChanged( bytes32 indexed node, bytes lastzonehash, bytes zonehash ); /** * zonehash obtains the hash for the zone. * @param node The RNS node to query. * @return The associated contenthash. */ function zonehash(bytes32 node) external view returns (bytes memory); }
IERC1155.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
InterfaceResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../ResolverBase.sol"; import "./AddrResolver.sol"; import "./IInterfaceResolver.sol"; abstract contract InterfaceResolver is IInterfaceResolver, AddrResolver { mapping(uint64 => mapping(bytes32 => mapping(bytes4 => address))) versionable_interfaces; /** * Sets an interface associated with a name. * Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support. * @param node The node to update. * @param interfaceID The EIP 165 interface ID. * @param implementer The address of a contract that implements this interface for this node. */ function setInterface( bytes32 node, bytes4 interfaceID, address implementer ) external virtual authorised(node) { versionable_interfaces[recordVersions[node]][node][ interfaceID ] = implementer; emit InterfaceChanged(node, interfaceID, implementer); } /** * Returns the address of a contract that implements the specified interface for this name. * If an implementer has not been set for this interfaceID and name, the resolver will query * the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that * contract implements EIP165 and returns `true` for the specified interfaceID, its address * will be returned. * @param node The RNS node to query. * @param interfaceID The EIP 165 interface ID to check for. * @return The address that implements this interface, or 0 if the interface is unsupported. */ function interfaceImplementer( bytes32 node, bytes4 interfaceID ) external view virtual override returns (address) { address implementer = versionable_interfaces[recordVersions[node]][ node ][interfaceID]; if (implementer != address(0)) { return implementer; } address a = addr(node); if (a == address(0)) { return address(0); } (bool success, bytes memory returnData) = a.staticcall( abi.encodeWithSignature( "supportsInterface(bytes4)", type(IERC165).interfaceId ) ); if (!success || returnData.length < 32 || returnData[31] == 0) { // EIP 165 not supported by target return address(0); } (success, returnData) = a.staticcall( abi.encodeWithSignature("supportsInterface(bytes4)", interfaceID) ); if (!success || returnData.length < 32 || returnData[31] == 0) { // Specified interface not supported by target return address(0); } return a; } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IInterfaceResolver).interfaceId || super.supportsInterface(interfaceID); } }
IDNSRecordResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface IDNSRecordResolver { // DNSRecordChanged is emitted whenever a given node/name/resource's RRSET is updated. event DNSRecordChanged( bytes32 indexed node, bytes name, uint16 resource, bytes record ); // DNSRecordDeleted is emitted whenever a given node/name/resource's RRSET is deleted. event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource); /** * Obtain a DNS record. * @param node the namehash of the node for which to fetch the record * @param name the keccak-256 hash of the fully-qualified name for which to fetch the record * @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types * @return the DNS record in wire format if present, otherwise empty */ function dnsRecord( bytes32 node, bytes32 name, uint16 resource ) external view returns (bytes memory); }
IInterfaceResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface IInterfaceResolver { event InterfaceChanged( bytes32 indexed node, bytes4 indexed interfaceID, address implementer ); /** * Returns the address of a contract that implements the specified interface for this name. * If an implementer has not been set for this interfaceID and name, the resolver will query * the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that * contract implements EIP165 and returns `true` for the specified interfaceID, its address * will be returned. * @param node The RNS node to query. * @param interfaceID The EIP 165 interface ID to check for. * @return The address that implements this interface, or 0 if the interface is unsupported. */ function interfaceImplementer( bytes32 node, bytes4 interfaceID ) external view returns (address); }
ContentHashResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import "../ResolverBase.sol"; import "./IContentHashResolver.sol"; abstract contract ContentHashResolver is IContentHashResolver, ResolverBase { mapping(uint64 => mapping(bytes32 => bytes)) versionable_hashes; /** * Sets the contenthash associated with an RNS node. * May only be called by the owner of that node in the RNS registry. * @param node The node to update. * @param hash The contenthash to set */ function setContenthash( bytes32 node, bytes calldata hash ) external virtual authorised(node) { versionable_hashes[recordVersions[node]][node] = hash; emit ContenthashChanged(node, hash); } /** * Returns the contenthash associated with an RNS node. * @param node The RNS node to query. * @return The associated contenthash. */ function contenthash( bytes32 node ) external view virtual override returns (bytes memory) { return versionable_hashes[recordVersions[node]][node]; } function supportsInterface( bytes4 interfaceID ) public view virtual override returns (bool) { return interfaceID == type(IContentHashResolver).interfaceId || super.supportsInterface(interfaceID); } }
IContentHashResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface IContentHashResolver { event ContenthashChanged(bytes32 indexed node, bytes hash); /** * Returns the contenthash associated with an RNS node. * @param node The RNS node to query. * @return The associated contenthash. */ function contenthash(bytes32 node) external view returns (bytes memory); }
IVersionableResolver.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; interface IVersionableResolver { event VersionChanged(bytes32 indexed node, uint64 newVersion); function recordVersions(bytes32 node) external view returns (uint64); }
ERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 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); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
IERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * 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[EIP 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: