Address: 0xeC7439BA799AbE63CB1f50ae4BdA09c9d0E953a2
Balance (XRP): 0 XRP
Bytecode: 0x608060405234801561001057600080fd5b50600436106101c45760003560e01c8063715018a6116100f9578063c869023311610097578063d700ff3311610071578063d700ff3314610450578063e59d895d14610493578063f1cb7e06146104a6578063f2fde38b146104b957600080fd5b8063c8690233146103d0578063ce3decdc1461042a578063d5fa2b001461043d57600080fd5b80638da5cb5b116100d35780638da5cb5b146103865780639061b92314610397578063a8fa5682146103aa578063bc1c58d1146103bd57600080fd5b8063715018a61461035857806377372213146103605780638b95dd711461037357600080fd5b80633603d7581161016657806359d1d43c1161014057806359d1d43c146102ff5780635c98042b1461031f578063623195b014610332578063691f34311461034557600080fd5b80633603d7581461028b5780633b3b57de1461029e5780634cbf6ba4146102b157600080fd5b8063124a319c116101a2578063124a319c146102195780632203ab561461024457806329cd62ea14610265578063304e6ade1461027857600080fd5b806301ffc9a7146101c95780630af179d7146101f157806310f13a8c14610206575b600080fd5b6101dc6101d736600461205c565b6104cc565b60405190151581526020015b60405180910390f35b6102046101ff3660046120b9565b6104dd565b005b610204610214366004612105565b6106ef565b61022c61022736600461217f565b6107c4565b6040516001600160a01b0390911681526020016101e8565b6102576102523660046121ab565b610a72565b6040516101e892919061221d565b610204610273366004612236565b610baa565b6102046102863660046120b9565b610c52565b610204610299366004612262565b610cd6565b61022c6102ac366004612262565b610d81565b6101dc6102bf3660046121ab565b60008281526001602090815260408083205467ffffffffffffffff1683526007825280832094835293815283822092825291909152205461ffff16151590565b61031261030d3660046120b9565b610db3565b6040516101e8919061227b565b61031261032d366004612262565b610e95565b61020461034036600461228e565b610f56565b610312610353366004612262565b610ffb565b610204611037565b61020461036e3660046120b9565b61104b565b610204610381366004612384565b6110cf565b6000546001600160a01b031661022c565b6103126103a53660046123d4565b6111b7565b6103126103b8366004612438565b611230565b6103126103cb366004612262565b611280565b6104156103de366004612262565b60008181526001602081815260408084205467ffffffffffffffff168452600a825280842094845293905291902080549101549091565b604080519283526020830191909152016101e8565b6102046104383660046120b9565b6112bc565b61020461044b36600461248f565b611407565b61047a61045e366004612262565b60016020526000908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101e8565b6102046104a13660046124b2565b611434565b6103126104b43660046121ab565b6114f0565b6102046104c73660046124ee565b6115ba565b60006104d78261164f565b92915050565b60005483906001600160a01b031633146104f657600080fd5b6000848152600160209081526040808320548151601f870184900484028101840190925285825283926060928392859267ffffffffffffffff90911691839161055e9183918d908d9081908401838280828437600092019190915250929392505061168d9050565b90505b80515160208201511015610688578661ffff166000036105c6578060400151965061058b816116ee565b94508460405160200161059e9190612509565b6040516020818303038152906040528051906020012092506105bf8161170f565b935061067a565b60006105d1826116ee565b9050816040015161ffff168861ffff161415806105f557506105f3868261172b565b155b15610678576106518c878a8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505060208801518d915061064890829061253b565b8b51158a611749565b8160400151975081602001519650809550858051906020012093506106758261170f565b94505b505b610683816119b6565b610561565b508351156106e3576106e38a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c92506106da91508290508f61253b565b89511588611749565b50505050505050505050565b60005485906001600160a01b0316331461070857600080fd5b60008681526001602090815260408083205467ffffffffffffffff168352600b82528083208984529091529081902090518491849161074a908990899061254e565b908152602001604051809103902091826107659291906125e6565b50848460405161077692919061254e565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a1878787876040516107b494939291906126cf565b60405180910390a3505050505050565b60008281526001602090815260408083205467ffffffffffffffff1683526008825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b0316801561081a5790506104d7565b600061082585610d81565b90506001600160a01b038116610840576000925050506104d7565b6040516301ffc9a760e01b602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b179052516108ad9190612509565b600060405180830381855afa9150503d80600081146108e8576040519150601f19603f3d011682016040523d82523d6000602084013e6108ed565b606091505b5091509150811580610900575060208151105b80610942575080601f8151811061091957610919612701565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b156109545760009450505050506104d7565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b179052516109bf9190612509565b600060405180830381855afa9150503d80600081146109fa576040519150601f19603f3d011682016040523d82523d6000602084013e6109ff565b606091505b509092509050811580610a13575060208151105b80610a55575080601f81518110610a2c57610a2c612701565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610a675760009450505050506104d7565b509095945050505050565b60008281526001602081815260408084205467ffffffffffffffff1684526002825280842086855290915282206060915b848111610b8a5780851615801590610ad3575060008181526020839052604081208054610acf9061255e565b9050115b15610b825780826000838152602001908152602001600020808054610af79061255e565b80601f0160208091040260200160405190810160405280929190818152602001828054610b239061255e565b8015610b705780601f10610b4557610100808354040283529160200191610b70565b820191906000526020600020905b815481529060010190602001808311610b5357829003601f168201915b50505050509050935093505050610ba3565b60011b610aa3565b5060006040518060200160405280600081525092509250505b9250929050565b60005483906001600160a01b03163314610bc357600080fd5b6040805180820182528481526020808201858152600088815260018084528582205467ffffffffffffffff168252600a84528582208a835290935284902092518355519101555184907f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4690610c449086908690918252602082015260400190565b60405180910390a250505050565b60005483906001600160a01b03163314610c6b57600080fd5b60008481526001602090815260408083205467ffffffffffffffff168352600482528083208784529091529020610ca38385836125e6565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788484604051610c44929190612717565b60005481906001600160a01b03163314610cef57600080fd5b6000828152600160205260408120805467ffffffffffffffff1691610d138361272b565b82546101009290920a67ffffffffffffffff8181021990931691831602179091556000848152600160209081526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b600080610d8f83603c6114f0565b90508051600003610da35750600092915050565b610dac81611a9e565b9392505050565b60008381526001602090815260408083205467ffffffffffffffff168352600b825280832086845290915290819020905160609190610df5908590859061254e565b90815260200160405180910390208054610e0e9061255e565b80601f0160208091040260200160405190810160405280929190818152602001828054610e3a9061255e565b8015610e875780601f10610e5c57610100808354040283529160200191610e87565b820191906000526020600020905b815481529060010190602001808311610e6a57829003601f168201915b505050505090509392505050565b60008181526001602090815260408083205467ffffffffffffffff168352600582528083208484529091529020805460609190610ed19061255e565b80601f0160208091040260200160405190810160405280929190818152602001828054610efd9061255e565b8015610f4a5780601f10610f1f57610100808354040283529160200191610f4a565b820191906000526020600020905b815481529060010190602001808311610f2d57829003601f168201915b50505050509050919050565b60005484906001600160a01b03163314610f6f57600080fd5b83610f7b60018261253b565b1615610f8657600080fd5b60008581526001602090815260408083205467ffffffffffffffff1683526002825280832088845282528083208784529091529020610fc68385836125e6565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe390600090a35050505050565b60008181526001602090815260408083205467ffffffffffffffff168352600982528083208484529091529020805460609190610ed19061255e565b61103f611ac6565b6110496000611b20565b565b60005483906001600160a01b0316331461106457600080fd5b60008481526001602090815260408083205467ffffffffffffffff16835260098252808320878452909152902061109c8385836125e6565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051610c44929190612717565b60005483906001600160a01b031633146110e857600080fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af752848460405161111a92919061221d565b60405180910390a2603c830361117157837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd261115584611a9e565b6040516001600160a01b03909116815260200160405180910390a25b60008481526001602090815260408083205467ffffffffffffffff16835260038252808320878452825280832086845290915290206111b08382612752565b5050505050565b6060600080306001600160a01b0316846040516111d49190612509565b600060405180830381855afa9150503d806000811461120f576040519150601f19603f3d011682016040523d82523d6000602084013e611214565b606091505b509150915081156112285791506104d79050565b805160208201fd5b60008381526001602090815260408083205467ffffffffffffffff168352600682528083208684528252808320858452825280832061ffff851684529091529020805460609190610e0e9061255e565b60008181526001602090815260408083205467ffffffffffffffff168352600482528083208484529091529020805460609190610ed19061255e565b60005483906001600160a01b031633146112d557600080fd5b60008481526001602090815260408083205467ffffffffffffffff1680845260058352818420888552909252822080549192916113119061255e565b80601f016020809104026020016040519081016040528092919081815260200182805461133d9061255e565b801561138a5780601f1061135f5761010080835404028352916020019161138a565b820191906000526020600020905b81548152906001019060200180831161136d57829003601f168201915b5050505067ffffffffffffffff841660009081526005602090815260408083208b845290915290209192506113c290508587836125e6565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f858287876040516113f793929190612812565b60405180910390a2505050505050565b60005482906001600160a01b0316331461142057600080fd5b61142f83603c61038185611b7d565b505050565b60005483906001600160a01b0316331461144d57600080fd5b60008481526001602090815260408083205467ffffffffffffffff1683526008825280832087845282528083206001600160e01b0319871680855290835292819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b60008281526001602090815260408083205467ffffffffffffffff16835260038252808320858452825280832084845290915290208054606091906115349061255e565b80601f01602080910402602001604051908101604052809291908181526020018280546115609061255e565b80156115ad5780601f10611582576101008083540402835291602001916115ad565b820191906000526020600020905b81548152906001019060200180831161159057829003601f168201915b5050505050905092915050565b6115c2611ac6565b6001600160a01b0381166116435760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61164c81611b20565b50565b60006001600160e01b031982167f59d1d43c0000000000000000000000000000000000000000000000000000000014806104d757506104d782611bb6565b6116db6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b82815260c081018290526104d7816119b6565b602081015181516060916104d7916117069082611bf4565b84519190611c56565b60a081015160c08201516060916104d79161170690829061253b565b600081518351148015610dac5750610dac8360008460008751611ccd565b86516020880120600061175d878787611c56565b905083156118875767ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152902080546117a89061255e565b1590506118075767ffffffffffffffff831660009081526007602090815260408083208d845282528083208584529091528120805461ffff16916117eb83612842565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152812061184891611ff1565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a60405161187a929190612860565b60405180910390a26106e3565b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152902080546118ca9061255e565b905060000361192b5767ffffffffffffffff831660009081526007602090815260408083208d845282528083208584529091528120805461ffff169161190f83612886565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff831660009081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152902061196d8282612752565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a846040516119a29392919061289d565b60405180910390a250505050505050505050565b60c081015160208201819052815151116119cd5750565b60006119e182600001518360200151611bf4565b82602001516119f091906128cc565b82519091506119ff9082611cf0565b61ffff166040830152611a136002826128cc565b8251909150611a229082611cf0565b61ffff166060830152611a366002826128cc565b8251909150611a459082611d18565b63ffffffff166080830152611a5b6004826128cc565b8251909150600090611a6d9083611cf0565b61ffff169050611a7e6002836128cc565b60a084018190529150611a9181836128cc565b60c0909301929092525050565b60008151601414611aae57600080fd5b50602001516c01000000000000000000000000900490565b6000546001600160a01b031633146110495760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161163a565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160148082528183019092526060916020820181803683375050506c010000000000000000000000009290920260208301525090565b60006001600160e01b031982167fc86902330000000000000000000000000000000000000000000000000000000014806104d757506104d782611d42565b6000815b83518110611c0857611c086128df565b6000611c148583611d80565b60ff169050611c248160016128cc565b611c2e90836128cc565b915080600003611c3e5750611c44565b50611bf8565b611c4e838261253b565b949350505050565b8251606090611c6583856128cc565b1115611c7057600080fd5b60008267ffffffffffffffff811115611c8b57611c8b6122e1565b6040519080825280601f01601f191660200182016040528015611cb5576020820181803683370190505b50905060208082019086860101610a67828287611da4565b6000611cda848484611dfa565b611ce5878785611dfa565b149695505050505050565b8151600090611d008360026128cc565b1115611d0b57600080fd5b50016002015161ffff1690565b8151600090611d288360046128cc565b1115611d3357600080fd5b50016004015163ffffffff1690565b60006001600160e01b031982167f691f34310000000000000000000000000000000000000000000000000000000014806104d757506104d782611e1e565b6000828281518110611d9457611d94612701565b016020015160f81c905092915050565b60208110611ddc5781518352611dbb6020846128cc565b9250611dc86020836128cc565b9150611dd560208261253b565b9050611da4565b905182516020929092036101000a6000190180199091169116179052565b8251600090611e0983856128cc565b1115611e1457600080fd5b5091016020012090565b60006001600160e01b031982167f124a319c0000000000000000000000000000000000000000000000000000000014806104d757506104d78260006001600160e01b031982167fa8fa5682000000000000000000000000000000000000000000000000000000001480611eba57506001600160e01b031982167f5c98042b00000000000000000000000000000000000000000000000000000000145b806104d757506104d78260006001600160e01b031982167fbc1c58d10000000000000000000000000000000000000000000000000000000014806104d757506104d78260006001600160e01b031982167f3b3b57de000000000000000000000000000000000000000000000000000000001480611f6057506001600160e01b031982167ff1cb7e0600000000000000000000000000000000000000000000000000000000145b806104d757506104d78260006001600160e01b031982167f2203ab560000000000000000000000000000000000000000000000000000000014806104d757506104d78260006001600160e01b031982167fd700ff330000000000000000000000000000000000000000000000000000000014806104d757506301ffc9a760e01b6001600160e01b03198316146104d7565b508054611ffd9061255e565b6000825580601f1061200d575050565b601f01602090049060005260206000209081019061164c91905b8082111561203b5760008155600101612027565b5090565b80356001600160e01b03198116811461205757600080fd5b919050565b60006020828403121561206e57600080fd5b610dac8261203f565b60008083601f84011261208957600080fd5b50813567ffffffffffffffff8111156120a157600080fd5b602083019150836020828501011115610ba357600080fd5b6000806000604084860312156120ce57600080fd5b83359250602084013567ffffffffffffffff8111156120ec57600080fd5b6120f886828701612077565b9497909650939450505050565b60008060008060006060868803121561211d57600080fd5b85359450602086013567ffffffffffffffff8082111561213c57600080fd5b61214889838a01612077565b9096509450604088013591508082111561216157600080fd5b5061216e88828901612077565b969995985093965092949392505050565b6000806040838503121561219257600080fd5b823591506121a26020840161203f565b90509250929050565b600080604083850312156121be57600080fd5b50508035926020909101359150565b60005b838110156121e85781810151838201526020016121d0565b50506000910152565b600081518084526122098160208601602086016121cd565b601f01601f19169290920160200192915050565b828152604060208201526000611c4e60408301846121f1565b60008060006060848603121561224b57600080fd5b505081359360208301359350604090920135919050565b60006020828403121561227457600080fd5b5035919050565b602081526000610dac60208301846121f1565b600080600080606085870312156122a457600080fd5b8435935060208501359250604085013567ffffffffffffffff8111156122c957600080fd5b6122d587828801612077565b95989497509550505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261230857600080fd5b813567ffffffffffffffff80821115612323576123236122e1565b604051601f8301601f19908116603f0116810190828211818310171561234b5761234b6122e1565b8160405283815286602085880101111561236457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561239957600080fd5b8335925060208401359150604084013567ffffffffffffffff8111156123be57600080fd5b6123ca868287016122f7565b9150509250925092565b600080604083850312156123e757600080fd5b823567ffffffffffffffff808211156123ff57600080fd5b61240b868387016122f7565b9350602085013591508082111561242157600080fd5b5061242e858286016122f7565b9150509250929050565b60008060006060848603121561244d57600080fd5b8335925060208401359150604084013561ffff8116811461246d57600080fd5b809150509250925092565b80356001600160a01b038116811461205757600080fd5b600080604083850312156124a257600080fd5b823591506121a260208401612478565b6000806000606084860312156124c757600080fd5b833592506124d76020850161203f565b91506124e560408501612478565b90509250925092565b60006020828403121561250057600080fd5b610dac82612478565b6000825161251b8184602087016121cd565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b818103818111156104d7576104d7612525565b8183823760009101908152919050565b600181811c9082168061257257607f821691505b60208210810361259257634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561142f57600081815260208120601f850160051c810160208610156125bf5750805b601f850160051c820191505b818110156125de578281556001016125cb565b505050505050565b67ffffffffffffffff8311156125fe576125fe6122e1565b6126128361260c835461255e565b83612598565b6000601f841160018114612646576000851561262e5750838201355b600019600387901b1c1916600186901b1783556111b0565b600083815260209020601f19861690835b828110156126775786850135825560209485019460019092019101612657565b50868210156126945760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040815260006126e36040830186886126a6565b82810360208401526126f68185876126a6565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b602081526000611c4e6020830184866126a6565b600067ffffffffffffffff80831681810361274857612748612525565b6001019392505050565b815167ffffffffffffffff81111561276c5761276c6122e1565b6127808161277a845461255e565b84612598565b602080601f8311600181146127b5576000841561279d5750858301515b600019600386901b1c1916600185901b1785556125de565b600085815260208120601f198616915b828110156127e4578886015182559484019460019091019084016127c5565b50858210156128025787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061282560408301866121f1565b82810360208401526128388185876126a6565b9695505050505050565b600061ffff82168061285657612856612525565b6000190192915050565b60408152600061287360408301856121f1565b905061ffff831660208301529392505050565b600061ffff80831681810361274857612748612525565b6060815260006128b060608301866121f1565b61ffff85166020840152828103604084015261283881856121f1565b808201808211156104d7576104d7612525565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220403dd0bf03242f725b8cbbfd903770f5d17c8c6b86ee321c0badf067bb9baa0964736f6c63430008110033
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); } }
OwnedResolver.sol
pragma solidity >=0.8.4; import "@openzeppelin/contracts/access/Ownable.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 "./profiles/ExtendedResolver.sol"; /** * A simple resolver anyone can use; only allows the owner of a node to set its * address. */ contract OwnedResolver is Ownable, ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver, ExtendedResolver { function isAuthorised(bytes32) internal view override returns (bool) { return msg.sender == owner(); } function supportsInterface( bytes4 interfaceID ) public view virtual override( ABIResolver, AddrResolver, ContentHashResolver, DNSResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver ) returns (bool) { return 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; } }
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; } }
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); } }
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); } }
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); }
ExtendedResolver.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; contract ExtendedResolver { function resolve( bytes memory /* name */, bytes memory data ) external view returns (bytes memory) { (bool success, bytes memory result) = address(this).staticcall(data); if (success) { return result; } else { // Revert with the reason provided by the call assembly { revert(add(result, 0x20), mload(result)) } } } }
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); }
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: