chai-link 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +5 -0
- package/contracts/Aggregator.sol +420 -0
- package/contracts/AggregatorProxy.sol +99 -0
- package/contracts/Chainlink.sol +125 -0
- package/contracts/ChainlinkClient.sol +262 -0
- package/contracts/Chainlinked.sol +141 -0
- package/contracts/Migrations.sol +23 -0
- package/contracts/Oracle.sol +320 -0
- package/contracts/Pointer.sol +9 -0
- package/contracts/interfaces/AggregatorInterface.sol +12 -0
- package/contracts/interfaces/ChainlinkRequestInterface.sol +21 -0
- package/contracts/interfaces/ENSInterface.sol +26 -0
- package/contracts/interfaces/LinkTokenInterface.sol +16 -0
- package/contracts/interfaces/OracleInterface.sol +16 -0
- package/contracts/interfaces/PointerInterface.sol +5 -0
- package/contracts/tests/BasicConsumer.sol +13 -0
- package/contracts/tests/ConcreteChainlink.sol +76 -0
- package/contracts/tests/ConcreteChainlinked.sol +100 -0
- package/contracts/tests/ConcreteSignedSafeMath.sol +16 -0
- package/contracts/tests/Consumer.sol +47 -0
- package/contracts/tests/EmptyOracle.sol +19 -0
- package/contracts/tests/GetterSetter.sol +45 -0
- package/contracts/tests/MaliciousChainlink.sol +76 -0
- package/contracts/tests/MaliciousChainlinked.sol +109 -0
- package/contracts/tests/MaliciousConsumer.sol +54 -0
- package/contracts/tests/MaliciousRequester.sol +52 -0
- package/contracts/tests/UpdatableConsumer.sol +24 -0
- package/contracts/vendor/Buffer.sol +301 -0
- package/contracts/vendor/CBOR.sol +71 -0
- package/contracts/vendor/ENS.sol +26 -0
- package/contracts/vendor/ENSRegistry.sol +99 -0
- package/contracts/vendor/ENSResolver.sol +5 -0
- package/contracts/vendor/Ownable.sol +64 -0
- package/contracts/vendor/PublicResolver.sol +238 -0
- package/contracts/vendor/SafeMath.sol +52 -0
- package/contracts/vendor/SignedSafeMath.sol +21 -0
- package/dist/artifacts/Aggregator.json +580 -0
- package/dist/artifacts/AggregatorInterface.json +172 -0
- package/dist/artifacts/AggregatorProxy.json +294 -0
- package/dist/artifacts/BasicConsumer.json +250 -0
- package/dist/artifacts/Buffer.json +52 -0
- package/dist/artifacts/CBOR.json +56 -0
- package/dist/artifacts/Chainlink.json +60 -0
- package/dist/artifacts/ChainlinkClient.json +125 -0
- package/dist/artifacts/ChainlinkRequestInterface.json +121 -0
- package/dist/artifacts/Chainlinked.json +129 -0
- package/dist/artifacts/ConcreteChainlink.json +190 -0
- package/dist/artifacts/ConcreteChainlinked.json +387 -0
- package/dist/artifacts/ConcreteSignedSafeMath.json +80 -0
- package/dist/artifacts/Consumer.json +227 -0
- package/dist/artifacts/ENS.json +259 -0
- package/dist/artifacts/ENSInterface.json +259 -0
- package/dist/artifacts/ENSRegistry.json +269 -0
- package/dist/artifacts/ENSResolver.json +72 -0
- package/dist/artifacts/EmptyOracle.json +259 -0
- package/dist/artifacts/GetterSetter.json +278 -0
- package/dist/artifacts/LinkTokenInterface.json +292 -0
- package/dist/artifacts/MaliciousChainlink.json +60 -0
- package/dist/artifacts/MaliciousChainlinked.json +137 -0
- package/dist/artifacts/MaliciousConsumer.json +288 -0
- package/dist/artifacts/MaliciousRequester.json +266 -0
- package/dist/artifacts/Migrations.json +115 -0
- package/dist/artifacts/Oracle.json +426 -0
- package/dist/artifacts/OracleInterface.json +161 -0
- package/dist/artifacts/Ownable.json +125 -0
- package/dist/artifacts/Pointer.json +78 -0
- package/dist/artifacts/PointerInterface.json +67 -0
- package/dist/artifacts/PublicResolver.json +503 -0
- package/dist/artifacts/SafeMath.json +52 -0
- package/dist/artifacts/SignedSafeMath.json +52 -0
- package/dist/artifacts/UpdatableConsumer.json +287 -0
- package/dist/src/LinkToken.d.ts +40 -0
- package/dist/src/LinkToken.json +164 -0
- package/dist/src/contract.d.ts +13 -0
- package/dist/src/contract.js +3 -0
- package/dist/src/contract.js.map +1 -0
- package/dist/src/debug.d.ts +8 -0
- package/dist/src/debug.js +17 -0
- package/dist/src/debug.js.map +1 -0
- package/dist/src/generated/Aggregator.d.ts +372 -0
- package/dist/src/generated/AggregatorFactory.d.ts +13 -0
- package/dist/src/generated/AggregatorFactory.js +505 -0
- package/dist/src/generated/AggregatorFactory.js.map +1 -0
- package/dist/src/generated/AggregatorInterface.d.ts +110 -0
- package/dist/src/generated/AggregatorInterfaceFactory.d.ts +6 -0
- package/dist/src/generated/AggregatorInterfaceFactory.js +133 -0
- package/dist/src/generated/AggregatorInterfaceFactory.js.map +1 -0
- package/dist/src/generated/AggregatorProxy.d.ts +196 -0
- package/dist/src/generated/AggregatorProxyFactory.d.ts +12 -0
- package/dist/src/generated/AggregatorProxyFactory.js +263 -0
- package/dist/src/generated/AggregatorProxyFactory.js.map +1 -0
- package/dist/src/generated/BasicConsumer.d.ts +154 -0
- package/dist/src/generated/BasicConsumerFactory.d.ts +13 -0
- package/dist/src/generated/BasicConsumerFactory.js +183 -0
- package/dist/src/generated/BasicConsumerFactory.js.map +1 -0
- package/dist/src/generated/ChainlinkClient.d.ts +58 -0
- package/dist/src/generated/ChainlinkClientFactory.d.ts +12 -0
- package/dist/src/generated/ChainlinkClientFactory.js +66 -0
- package/dist/src/generated/ChainlinkClientFactory.js.map +1 -0
- package/dist/src/generated/ChainlinkRequestInterface.d.ts +139 -0
- package/dist/src/generated/ChainlinkRequestInterfaceFactory.d.ts +6 -0
- package/dist/src/generated/ChainlinkRequestInterfaceFactory.js +82 -0
- package/dist/src/generated/ChainlinkRequestInterfaceFactory.js.map +1 -0
- package/dist/src/generated/Chainlinked.d.ts +55 -0
- package/dist/src/generated/ChainlinkedFactory.d.ts +12 -0
- package/dist/src/generated/ChainlinkedFactory.js +66 -0
- package/dist/src/generated/ChainlinkedFactory.js.map +1 -0
- package/dist/src/generated/ConcreteChainlink.d.ts +158 -0
- package/dist/src/generated/ConcreteChainlinkFactory.d.ts +12 -0
- package/dist/src/generated/ConcreteChainlinkFactory.js +155 -0
- package/dist/src/generated/ConcreteChainlinkFactory.js.map +1 -0
- package/dist/src/generated/ConcreteChainlinked.d.ts +300 -0
- package/dist/src/generated/ConcreteChainlinkedFactory.d.ts +12 -0
- package/dist/src/generated/ConcreteChainlinkedFactory.js +320 -0
- package/dist/src/generated/ConcreteChainlinkedFactory.js.map +1 -0
- package/dist/src/generated/ConcreteSignedSafeMath.d.ts +50 -0
- package/dist/src/generated/ConcreteSignedSafeMathFactory.d.ts +12 -0
- package/dist/src/generated/ConcreteSignedSafeMathFactory.js +53 -0
- package/dist/src/generated/ConcreteSignedSafeMathFactory.js.map +1 -0
- package/dist/src/generated/Consumer.d.ts +151 -0
- package/dist/src/generated/ConsumerFactory.d.ts +12 -0
- package/dist/src/generated/ConsumerFactory.js +164 -0
- package/dist/src/generated/ConsumerFactory.js.map +1 -0
- package/dist/src/generated/ENS.d.ts +171 -0
- package/dist/src/generated/ENSFactory.d.ts +6 -0
- package/dist/src/generated/ENSFactory.js +220 -0
- package/dist/src/generated/ENSFactory.js.map +1 -0
- package/dist/src/generated/ENSInterface.d.ts +174 -0
- package/dist/src/generated/ENSInterfaceFactory.d.ts +6 -0
- package/dist/src/generated/ENSInterfaceFactory.js +220 -0
- package/dist/src/generated/ENSInterfaceFactory.js.map +1 -0
- package/dist/src/generated/ENSRegistry.d.ts +171 -0
- package/dist/src/generated/ENSRegistryFactory.d.ts +12 -0
- package/dist/src/generated/ENSRegistryFactory.js +242 -0
- package/dist/src/generated/ENSRegistryFactory.js.map +1 -0
- package/dist/src/generated/ENSResolver.d.ts +45 -0
- package/dist/src/generated/ENSResolverFactory.d.ts +6 -0
- package/dist/src/generated/ENSResolverFactory.js +33 -0
- package/dist/src/generated/ENSResolverFactory.js.map +1 -0
- package/dist/src/generated/EmptyOracle.d.ts +228 -0
- package/dist/src/generated/EmptyOracleFactory.d.ts +12 -0
- package/dist/src/generated/EmptyOracleFactory.js +228 -0
- package/dist/src/generated/EmptyOracleFactory.js.map +1 -0
- package/dist/src/generated/GetterSetter.d.ts +207 -0
- package/dist/src/generated/GetterSetterFactory.d.ts +12 -0
- package/dist/src/generated/GetterSetterFactory.js +255 -0
- package/dist/src/generated/GetterSetterFactory.js.map +1 -0
- package/dist/src/generated/LinkToken.d.ts +243 -0
- package/dist/src/generated/LinkTokenFactory.d.ts +12 -0
- package/dist/src/generated/LinkTokenFactory.js +329 -0
- package/dist/src/generated/LinkTokenFactory.js.map +1 -0
- package/dist/src/generated/LinkTokenInterface.d.ts +230 -0
- package/dist/src/generated/LinkTokenInterfaceFactory.d.ts +6 -0
- package/dist/src/generated/LinkTokenInterfaceFactory.js +253 -0
- package/dist/src/generated/LinkTokenInterfaceFactory.js.map +1 -0
- package/dist/src/generated/MaliciousChainlinked.d.ts +58 -0
- package/dist/src/generated/MaliciousChainlinkedFactory.d.ts +12 -0
- package/dist/src/generated/MaliciousChainlinkedFactory.js +66 -0
- package/dist/src/generated/MaliciousChainlinkedFactory.js.map +1 -0
- package/dist/src/generated/MaliciousConsumer.d.ts +179 -0
- package/dist/src/generated/MaliciousConsumerFactory.d.ts +12 -0
- package/dist/src/generated/MaliciousConsumerFactory.js +221 -0
- package/dist/src/generated/MaliciousConsumerFactory.js.map +1 -0
- package/dist/src/generated/MaliciousRequester.d.ts +161 -0
- package/dist/src/generated/MaliciousRequesterFactory.d.ts +12 -0
- package/dist/src/generated/MaliciousRequesterFactory.js +191 -0
- package/dist/src/generated/MaliciousRequesterFactory.js.map +1 -0
- package/dist/src/generated/Migrations.d.ts +87 -0
- package/dist/src/generated/MigrationsFactory.d.ts +12 -0
- package/dist/src/generated/MigrationsFactory.js +92 -0
- package/dist/src/generated/MigrationsFactory.js.map +1 -0
- package/dist/src/generated/Oracle.d.ts +362 -0
- package/dist/src/generated/OracleFactory.d.ts +12 -0
- package/dist/src/generated/OracleFactory.js +383 -0
- package/dist/src/generated/OracleFactory.js.map +1 -0
- package/dist/src/generated/OracleInterface.d.ts +144 -0
- package/dist/src/generated/OracleInterfaceFactory.d.ts +6 -0
- package/dist/src/generated/OracleInterfaceFactory.js +122 -0
- package/dist/src/generated/OracleInterfaceFactory.js.map +1 -0
- package/dist/src/generated/Ownable.d.ts +91 -0
- package/dist/src/generated/OwnableFactory.d.ts +12 -0
- package/dist/src/generated/OwnableFactory.js +102 -0
- package/dist/src/generated/OwnableFactory.js.map +1 -0
- package/dist/src/generated/Pointer.d.ts +45 -0
- package/dist/src/generated/PointerFactory.d.ts +12 -0
- package/dist/src/generated/PointerFactory.js +55 -0
- package/dist/src/generated/PointerFactory.js.map +1 -0
- package/dist/src/generated/PointerInterface.d.ts +48 -0
- package/dist/src/generated/PointerInterfaceFactory.d.ts +6 -0
- package/dist/src/generated/PointerInterfaceFactory.js +28 -0
- package/dist/src/generated/PointerInterfaceFactory.js.map +1 -0
- package/dist/src/generated/PublicResolver.d.ts +336 -0
- package/dist/src/generated/PublicResolverFactory.d.ts +12 -0
- package/dist/src/generated/PublicResolverFactory.js +476 -0
- package/dist/src/generated/PublicResolverFactory.js.map +1 -0
- package/dist/src/generated/UpdatableConsumer.d.ts +180 -0
- package/dist/src/generated/UpdatableConsumerFactory.d.ts +13 -0
- package/dist/src/generated/UpdatableConsumerFactory.js +220 -0
- package/dist/src/generated/UpdatableConsumerFactory.js.map +1 -0
- package/dist/src/generated/index.d.ts +44 -0
- package/dist/src/generated/index.js +41 -0
- package/dist/src/generated/index.js.map +1 -0
- package/dist/src/helpers.d.ts +144 -0
- package/dist/src/helpers.js +358 -0
- package/dist/src/helpers.js.map +1 -0
- package/dist/src/helpers.test.d.ts +1 -0
- package/dist/src/helpers.test.js +21 -0
- package/dist/src/helpers.test.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +27 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/matchers.d.ts +2 -0
- package/dist/src/matchers.js +7 -0
- package/dist/src/matchers.js.map +1 -0
- package/dist/src/provider.d.ts +5 -0
- package/dist/src/provider.js +15 -0
- package/dist/src/provider.js.map +1 -0
- package/dist/src/wallet.d.ts +35 -0
- package/dist/src/wallet.js +64 -0
- package/dist/src/wallet.js.map +1 -0
- package/dist/test/Aggregator.test.d.ts +1 -0
- package/dist/test/Aggregator.test.js +581 -0
- package/dist/test/Aggregator.test.js.map +1 -0
- package/dist/test/AggregatorProxy.test.d.ts +1 -0
- package/dist/test/AggregatorProxy.test.js +179 -0
- package/dist/test/AggregatorProxy.test.js.map +1 -0
- package/dist/test/BasicConsumer.test.d.ts +1 -0
- package/dist/test/BasicConsumer.test.js +180 -0
- package/dist/test/BasicConsumer.test.js.map +1 -0
- package/dist/test/Chainlinked.test.d.ts +1 -0
- package/dist/test/Chainlinked.test.js +11 -0
- package/dist/test/Chainlinked.test.js.map +1 -0
- package/dist/test/ConcreteChainlink.test.d.ts +1 -0
- package/dist/test/ConcreteChainlink.test.js +163 -0
- package/dist/test/ConcreteChainlink.test.js.map +1 -0
- package/dist/test/ConcreteChainlinked.test.d.ts +1 -0
- package/dist/test/ConcreteChainlinked.test.js +182 -0
- package/dist/test/ConcreteChainlinked.test.js.map +1 -0
- package/dist/test/GetterSetter.test.d.ts +1 -0
- package/dist/test/GetterSetter.test.js +76 -0
- package/dist/test/GetterSetter.test.js.map +1 -0
- package/dist/test/Oracle.test.d.ts +1 -0
- package/dist/test/Oracle.test.js +669 -0
- package/dist/test/Oracle.test.js.map +1 -0
- package/dist/test/Pointer.test.d.ts +1 -0
- package/dist/test/Pointer.test.js +35 -0
- package/dist/test/Pointer.test.js.map +1 -0
- package/dist/test/SignedSafeMath.test.d.ts +1 -0
- package/dist/test/SignedSafeMath.test.js +75 -0
- package/dist/test/SignedSafeMath.test.js.map +1 -0
- package/dist/test/UpdatableConsumer.test.d.ts +1 -0
- package/dist/test/UpdatableConsumer.test.js +144 -0
- package/dist/test/UpdatableConsumer.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +7737 -0
- package/package.json +50 -0
- package/r1z9aogk.cjs +1 -0
- package/v0.5/contracts/Chainlink.sol +125 -0
- package/v0.5/contracts/ChainlinkClient.sol +263 -0
- package/v0.5/contracts/LinkTokenReceiver.sol +70 -0
- package/v0.5/contracts/Median.sol +108 -0
- package/v0.5/contracts/Migrations.sol +23 -0
- package/v0.5/contracts/Oracle.sol +273 -0
- package/v0.5/contracts/PreCoordinator.sol +305 -0
- package/v0.5/contracts/dev/AggregatorInterface.sol +12 -0
- package/v0.5/contracts/dev/Coordinator.sol +411 -0
- package/v0.5/contracts/dev/CoordinatorInterface.sol +14 -0
- package/v0.5/contracts/dev/OracleSignaturesDecoder.sol +24 -0
- package/v0.5/contracts/dev/Owned.sol +61 -0
- package/v0.5/contracts/dev/PrepaidAggregator.sol +621 -0
- package/v0.5/contracts/dev/SafeMath128.sol +110 -0
- package/v0.5/contracts/dev/SafeMath32.sol +110 -0
- package/v0.5/contracts/dev/SafeMath64.sol +110 -0
- package/v0.5/contracts/dev/SchnorrSECP256K1.sol +147 -0
- package/v0.5/contracts/dev/ServiceAgreementDecoder.sol +59 -0
- package/v0.5/contracts/dev/VRF.sol +382 -0
- package/v0.5/contracts/dev/Whitelisted.sol +41 -0
- package/v0.5/contracts/dev/WhitelistedAggregator.sol +80 -0
- package/v0.5/contracts/interfaces/ChainlinkRequestInterface.sol +21 -0
- package/v0.5/contracts/interfaces/ENSInterface.sol +26 -0
- package/v0.5/contracts/interfaces/LinkTokenInterface.sol +16 -0
- package/v0.5/contracts/interfaces/OracleInterface.sol +16 -0
- package/v0.5/contracts/interfaces/PointerInterface.sol +5 -0
- package/v0.5/contracts/interfaces/WithdrawalInterface.sol +16 -0
- package/v0.5/contracts/tests/BasicConsumer.sol +13 -0
- package/v0.5/contracts/tests/ChainlinkTestHelper.sol +75 -0
- package/v0.5/contracts/tests/Consumer.sol +55 -0
- package/v0.5/contracts/tests/EmptyAggregator.sol +34 -0
- package/v0.5/contracts/tests/GetterSetter.sol +45 -0
- package/v0.5/contracts/tests/MaliciousChainlink.sol +75 -0
- package/v0.5/contracts/tests/MaliciousChainlinkClient.sol +109 -0
- package/v0.5/contracts/tests/MaliciousConsumer.sol +54 -0
- package/v0.5/contracts/tests/MaliciousRequester.sol +52 -0
- package/v0.5/contracts/tests/MeanAggregator.sol +75 -0
- package/v0.5/contracts/tests/MedianTestHelper.sol +15 -0
- package/v0.5/contracts/tests/OwnedTestHelper.sol +16 -0
- package/v0.5/contracts/tests/ServiceAgreementConsumer.sol +30 -0
- package/v0.5/contracts/vendor/Buffer.sol +301 -0
- package/v0.5/contracts/vendor/CBOR.sol +71 -0
- package/v0.5/contracts/vendor/ENSResolver.sol +5 -0
- package/v0.5/contracts/vendor/Ownable.sol +65 -0
- package/v0.5/contracts/vendor/SafeMath.sol +107 -0
- package/v0.5/contracts/vendor/SignedSafeMath.sol +22 -0
- package/v0.6/contracts/Chainlink.sol +125 -0
- package/v0.6/contracts/ChainlinkClient.sol +263 -0
- package/v0.6/contracts/LinkTokenReceiver.sol +70 -0
- package/v0.6/contracts/Oracle.sol +276 -0
- package/v0.6/contracts/interfaces/ChainlinkRequestInterface.sol +21 -0
- package/v0.6/contracts/interfaces/ENSInterface.sol +26 -0
- package/v0.6/contracts/interfaces/LinkTokenInterface.sol +16 -0
- package/v0.6/contracts/interfaces/OracleInterface.sol +16 -0
- package/v0.6/contracts/interfaces/PointerInterface.sol +5 -0
- package/v0.6/contracts/interfaces/WithdrawalInterface.sol +16 -0
- package/v0.6/contracts/tests/BasicConsumer.sol +13 -0
- package/v0.6/contracts/tests/Consumer.sol +55 -0
- package/v0.6/contracts/vendor/Buffer.sol +301 -0
- package/v0.6/contracts/vendor/CBOR.sol +71 -0
- package/v0.6/contracts/vendor/ENSResolver.sol +5 -0
- package/v0.6/contracts/vendor/Ownable.sol +65 -0
- package/v0.6/contracts/vendor/SafeMath.sol +107 -0
- package/zos.json +8 -0
- package/zos.rinkeby.json +104 -0
- package/zos.ropsten.json +104 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
pragma solidity ^0.4.19;
|
2
|
+
|
3
|
+
import "./Buffer.sol";
|
4
|
+
|
5
|
+
library CBOR {
|
6
|
+
using Buffer for Buffer.buffer;
|
7
|
+
|
8
|
+
uint8 private constant MAJOR_TYPE_INT = 0;
|
9
|
+
uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1;
|
10
|
+
uint8 private constant MAJOR_TYPE_BYTES = 2;
|
11
|
+
uint8 private constant MAJOR_TYPE_STRING = 3;
|
12
|
+
uint8 private constant MAJOR_TYPE_ARRAY = 4;
|
13
|
+
uint8 private constant MAJOR_TYPE_MAP = 5;
|
14
|
+
uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7;
|
15
|
+
|
16
|
+
function encodeType(Buffer.buffer memory buf, uint8 major, uint value) private pure {
|
17
|
+
if(value <= 23) {
|
18
|
+
buf.appendUint8(uint8((major << 5) | value));
|
19
|
+
} else if(value <= 0xFF) {
|
20
|
+
buf.appendUint8(uint8((major << 5) | 24));
|
21
|
+
buf.appendInt(value, 1);
|
22
|
+
} else if(value <= 0xFFFF) {
|
23
|
+
buf.appendUint8(uint8((major << 5) | 25));
|
24
|
+
buf.appendInt(value, 2);
|
25
|
+
} else if(value <= 0xFFFFFFFF) {
|
26
|
+
buf.appendUint8(uint8((major << 5) | 26));
|
27
|
+
buf.appendInt(value, 4);
|
28
|
+
} else if(value <= 0xFFFFFFFFFFFFFFFF) {
|
29
|
+
buf.appendUint8(uint8((major << 5) | 27));
|
30
|
+
buf.appendInt(value, 8);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
function encodeIndefiniteLengthType(Buffer.buffer memory buf, uint8 major) private pure {
|
35
|
+
buf.appendUint8(uint8((major << 5) | 31));
|
36
|
+
}
|
37
|
+
|
38
|
+
function encodeUInt(Buffer.buffer memory buf, uint value) internal pure {
|
39
|
+
encodeType(buf, MAJOR_TYPE_INT, value);
|
40
|
+
}
|
41
|
+
|
42
|
+
function encodeInt(Buffer.buffer memory buf, int value) internal pure {
|
43
|
+
if(value >= 0) {
|
44
|
+
encodeType(buf, MAJOR_TYPE_INT, uint(value));
|
45
|
+
} else {
|
46
|
+
encodeType(buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - value));
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
function encodeBytes(Buffer.buffer memory buf, bytes value) internal pure {
|
51
|
+
encodeType(buf, MAJOR_TYPE_BYTES, value.length);
|
52
|
+
buf.append(value);
|
53
|
+
}
|
54
|
+
|
55
|
+
function encodeString(Buffer.buffer memory buf, string value) internal pure {
|
56
|
+
encodeType(buf, MAJOR_TYPE_STRING, bytes(value).length);
|
57
|
+
buf.append(bytes(value));
|
58
|
+
}
|
59
|
+
|
60
|
+
function startArray(Buffer.buffer memory buf) internal pure {
|
61
|
+
encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY);
|
62
|
+
}
|
63
|
+
|
64
|
+
function startMap(Buffer.buffer memory buf) internal pure {
|
65
|
+
encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP);
|
66
|
+
}
|
67
|
+
|
68
|
+
function endSequence(Buffer.buffer memory buf) internal pure {
|
69
|
+
encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE);
|
70
|
+
}
|
71
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
pragma solidity ^0.4.24;
|
2
|
+
|
3
|
+
interface ENS {
|
4
|
+
|
5
|
+
// Logged when the owner of a node assigns a new owner to a subnode.
|
6
|
+
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
|
7
|
+
|
8
|
+
// Logged when the owner of a node transfers ownership to a new account.
|
9
|
+
event Transfer(bytes32 indexed node, address owner);
|
10
|
+
|
11
|
+
// Logged when the resolver for a node changes.
|
12
|
+
event NewResolver(bytes32 indexed node, address resolver);
|
13
|
+
|
14
|
+
// Logged when the TTL of a node changes
|
15
|
+
event NewTTL(bytes32 indexed node, uint64 ttl);
|
16
|
+
|
17
|
+
|
18
|
+
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public;
|
19
|
+
function setResolver(bytes32 node, address resolver) public;
|
20
|
+
function setOwner(bytes32 node, address owner) public;
|
21
|
+
function setTTL(bytes32 node, uint64 ttl) public;
|
22
|
+
function owner(bytes32 node) public view returns (address);
|
23
|
+
function resolver(bytes32 node) public view returns (address);
|
24
|
+
function ttl(bytes32 node) public view returns (uint64);
|
25
|
+
|
26
|
+
}
|
@@ -0,0 +1,99 @@
|
|
1
|
+
pragma solidity ^0.4.24;
|
2
|
+
|
3
|
+
import "./ENS.sol";
|
4
|
+
|
5
|
+
/**
|
6
|
+
* The ENS registry contract.
|
7
|
+
*/
|
8
|
+
contract ENSRegistry is ENS {
|
9
|
+
struct Record {
|
10
|
+
address owner;
|
11
|
+
address resolver;
|
12
|
+
uint64 ttl;
|
13
|
+
}
|
14
|
+
|
15
|
+
mapping (bytes32 => Record) records;
|
16
|
+
|
17
|
+
// Permits modifications only by the owner of the specified node.
|
18
|
+
modifier only_owner(bytes32 node) {
|
19
|
+
require(records[node].owner == msg.sender);
|
20
|
+
_;
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* @dev Constructs a new ENS registrar.
|
25
|
+
*/
|
26
|
+
constructor() public {
|
27
|
+
records[0x0].owner = msg.sender;
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node.
|
32
|
+
* @param node The node to transfer ownership of.
|
33
|
+
* @param owner The address of the new owner.
|
34
|
+
*/
|
35
|
+
function setOwner(bytes32 node, address owner) public only_owner(node) {
|
36
|
+
emit Transfer(node, owner);
|
37
|
+
records[node].owner = owner;
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node.
|
42
|
+
* @param node The parent node.
|
43
|
+
* @param label The hash of the label specifying the subnode.
|
44
|
+
* @param owner The address of the new owner.
|
45
|
+
*/
|
46
|
+
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public only_owner(node) {
|
47
|
+
bytes32 subnode = keccak256(abi.encodePacked(node, label));
|
48
|
+
emit NewOwner(node, label, owner);
|
49
|
+
records[subnode].owner = owner;
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* @dev Sets the resolver address for the specified node.
|
54
|
+
* @param node The node to update.
|
55
|
+
* @param resolver The address of the resolver.
|
56
|
+
*/
|
57
|
+
function setResolver(bytes32 node, address resolver) public only_owner(node) {
|
58
|
+
emit NewResolver(node, resolver);
|
59
|
+
records[node].resolver = resolver;
|
60
|
+
}
|
61
|
+
|
62
|
+
/**
|
63
|
+
* @dev Sets the TTL for the specified node.
|
64
|
+
* @param node The node to update.
|
65
|
+
* @param ttl The TTL in seconds.
|
66
|
+
*/
|
67
|
+
function setTTL(bytes32 node, uint64 ttl) public only_owner(node) {
|
68
|
+
emit NewTTL(node, ttl);
|
69
|
+
records[node].ttl = ttl;
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* @dev Returns the address that owns the specified node.
|
74
|
+
* @param node The specified node.
|
75
|
+
* @return address of the owner.
|
76
|
+
*/
|
77
|
+
function owner(bytes32 node) public view returns (address) {
|
78
|
+
return records[node].owner;
|
79
|
+
}
|
80
|
+
|
81
|
+
/**
|
82
|
+
* @dev Returns the address of the resolver for the specified node.
|
83
|
+
* @param node The specified node.
|
84
|
+
* @return address of the resolver.
|
85
|
+
*/
|
86
|
+
function resolver(bytes32 node) public view returns (address) {
|
87
|
+
return records[node].resolver;
|
88
|
+
}
|
89
|
+
|
90
|
+
/**
|
91
|
+
* @dev Returns the TTL of a node, and any records associated with it.
|
92
|
+
* @param node The specified node.
|
93
|
+
* @return ttl of the node.
|
94
|
+
*/
|
95
|
+
function ttl(bytes32 node) public view returns (uint64) {
|
96
|
+
return records[node].ttl;
|
97
|
+
}
|
98
|
+
|
99
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
pragma solidity ^0.4.24;
|
2
|
+
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @title Ownable
|
6
|
+
* @dev The Ownable contract has an owner address, and provides basic authorization control
|
7
|
+
* functions, this simplifies the implementation of "user permissions".
|
8
|
+
*/
|
9
|
+
contract Ownable {
|
10
|
+
address public owner;
|
11
|
+
|
12
|
+
|
13
|
+
event OwnershipRenounced(address indexed previousOwner);
|
14
|
+
event OwnershipTransferred(
|
15
|
+
address indexed previousOwner,
|
16
|
+
address indexed newOwner
|
17
|
+
);
|
18
|
+
|
19
|
+
|
20
|
+
/**
|
21
|
+
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
|
22
|
+
* account.
|
23
|
+
*/
|
24
|
+
constructor() public {
|
25
|
+
owner = msg.sender;
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* @dev Throws if called by any account other than the owner.
|
30
|
+
*/
|
31
|
+
modifier onlyOwner() {
|
32
|
+
require(msg.sender == owner);
|
33
|
+
_;
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* @dev Allows the current owner to relinquish control of the contract.
|
38
|
+
* @notice Renouncing to ownership will leave the contract without an owner.
|
39
|
+
* It will not be possible to call the functions with the `onlyOwner`
|
40
|
+
* modifier anymore.
|
41
|
+
*/
|
42
|
+
function renounceOwnership() public onlyOwner {
|
43
|
+
emit OwnershipRenounced(owner);
|
44
|
+
owner = address(0);
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* @dev Allows the current owner to transfer control of the contract to a newOwner.
|
49
|
+
* @param _newOwner The address to transfer ownership to.
|
50
|
+
*/
|
51
|
+
function transferOwnership(address _newOwner) public onlyOwner {
|
52
|
+
_transferOwnership(_newOwner);
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* @dev Transfers control of the contract to a newOwner.
|
57
|
+
* @param _newOwner The address to transfer ownership to.
|
58
|
+
*/
|
59
|
+
function _transferOwnership(address _newOwner) internal {
|
60
|
+
require(_newOwner != address(0));
|
61
|
+
emit OwnershipTransferred(owner, _newOwner);
|
62
|
+
owner = _newOwner;
|
63
|
+
}
|
64
|
+
}
|
@@ -0,0 +1,238 @@
|
|
1
|
+
pragma solidity ^0.4.24;
|
2
|
+
|
3
|
+
import "./ENS.sol";
|
4
|
+
|
5
|
+
/**
|
6
|
+
* A simple resolver anyone can use; only allows the owner of a node to set its
|
7
|
+
* address.
|
8
|
+
*/
|
9
|
+
contract PublicResolver {
|
10
|
+
|
11
|
+
bytes4 constant INTERFACE_META_ID = 0x01ffc9a7;
|
12
|
+
bytes4 constant ADDR_INTERFACE_ID = 0x3b3b57de;
|
13
|
+
bytes4 constant CONTENT_INTERFACE_ID = 0xd8389dc5;
|
14
|
+
bytes4 constant NAME_INTERFACE_ID = 0x691f3431;
|
15
|
+
bytes4 constant ABI_INTERFACE_ID = 0x2203ab56;
|
16
|
+
bytes4 constant PUBKEY_INTERFACE_ID = 0xc8690233;
|
17
|
+
bytes4 constant TEXT_INTERFACE_ID = 0x59d1d43c;
|
18
|
+
bytes4 constant MULTIHASH_INTERFACE_ID = 0xe89401a1;
|
19
|
+
|
20
|
+
event AddrChanged(bytes32 indexed node, address a);
|
21
|
+
event ContentChanged(bytes32 indexed node, bytes32 hash);
|
22
|
+
event NameChanged(bytes32 indexed node, string name);
|
23
|
+
event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
|
24
|
+
event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
|
25
|
+
event TextChanged(bytes32 indexed node, string indexedKey, string key);
|
26
|
+
event MultihashChanged(bytes32 indexed node, bytes hash);
|
27
|
+
|
28
|
+
struct PublicKey {
|
29
|
+
bytes32 x;
|
30
|
+
bytes32 y;
|
31
|
+
}
|
32
|
+
|
33
|
+
struct Record {
|
34
|
+
address addr;
|
35
|
+
bytes32 content;
|
36
|
+
string name;
|
37
|
+
PublicKey pubkey;
|
38
|
+
mapping(string=>string) text;
|
39
|
+
mapping(uint256=>bytes) abis;
|
40
|
+
bytes multihash;
|
41
|
+
}
|
42
|
+
|
43
|
+
ENS ens;
|
44
|
+
|
45
|
+
mapping (bytes32 => Record) records;
|
46
|
+
|
47
|
+
modifier only_owner(bytes32 node) {
|
48
|
+
require(ens.owner(node) == msg.sender);
|
49
|
+
_;
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Constructor.
|
54
|
+
* @param ensAddr The ENS registrar contract.
|
55
|
+
*/
|
56
|
+
constructor(ENS ensAddr) public {
|
57
|
+
ens = ensAddr;
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* Sets the address associated with an ENS node.
|
62
|
+
* May only be called by the owner of that node in the ENS registry.
|
63
|
+
* @param node The node to update.
|
64
|
+
* @param addr The address to set.
|
65
|
+
*/
|
66
|
+
function setAddr(bytes32 node, address addr) public only_owner(node) {
|
67
|
+
records[node].addr = addr;
|
68
|
+
emit AddrChanged(node, addr);
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
* Sets the content hash associated with an ENS node.
|
73
|
+
* May only be called by the owner of that node in the ENS registry.
|
74
|
+
* Note that this resource type is not standardized, and will likely change
|
75
|
+
* in future to a resource type based on multihash.
|
76
|
+
* @param node The node to update.
|
77
|
+
* @param hash The content hash to set
|
78
|
+
*/
|
79
|
+
function setContent(bytes32 node, bytes32 hash) public only_owner(node) {
|
80
|
+
records[node].content = hash;
|
81
|
+
emit ContentChanged(node, hash);
|
82
|
+
}
|
83
|
+
|
84
|
+
/**
|
85
|
+
* Sets the multihash associated with an ENS node.
|
86
|
+
* May only be called by the owner of that node in the ENS registry.
|
87
|
+
* @param node The node to update.
|
88
|
+
* @param hash The multihash to set
|
89
|
+
*/
|
90
|
+
function setMultihash(bytes32 node, bytes hash) public only_owner(node) {
|
91
|
+
records[node].multihash = hash;
|
92
|
+
emit MultihashChanged(node, hash);
|
93
|
+
}
|
94
|
+
|
95
|
+
/**
|
96
|
+
* Sets the name associated with an ENS node, for reverse records.
|
97
|
+
* May only be called by the owner of that node in the ENS registry.
|
98
|
+
* @param node The node to update.
|
99
|
+
* @param name The name to set.
|
100
|
+
*/
|
101
|
+
function setName(bytes32 node, string name) public only_owner(node) {
|
102
|
+
records[node].name = name;
|
103
|
+
emit NameChanged(node, name);
|
104
|
+
}
|
105
|
+
|
106
|
+
/**
|
107
|
+
* Sets the ABI associated with an ENS node.
|
108
|
+
* Nodes may have one ABI of each content type. To remove an ABI, set it to
|
109
|
+
* the empty string.
|
110
|
+
* @param node The node to update.
|
111
|
+
* @param contentType The content type of the ABI
|
112
|
+
* @param data The ABI data.
|
113
|
+
*/
|
114
|
+
function setABI(bytes32 node, uint256 contentType, bytes data) public only_owner(node) {
|
115
|
+
// Content types must be powers of 2
|
116
|
+
require(((contentType - 1) & contentType) == 0);
|
117
|
+
|
118
|
+
records[node].abis[contentType] = data;
|
119
|
+
emit ABIChanged(node, contentType);
|
120
|
+
}
|
121
|
+
|
122
|
+
/**
|
123
|
+
* Sets the SECP256k1 public key associated with an ENS node.
|
124
|
+
* @param node The ENS node to query
|
125
|
+
* @param x the X coordinate of the curve point for the public key.
|
126
|
+
* @param y the Y coordinate of the curve point for the public key.
|
127
|
+
*/
|
128
|
+
function setPubkey(bytes32 node, bytes32 x, bytes32 y) public only_owner(node) {
|
129
|
+
records[node].pubkey = PublicKey(x, y);
|
130
|
+
emit PubkeyChanged(node, x, y);
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Sets the text data associated with an ENS node and key.
|
135
|
+
* May only be called by the owner of that node in the ENS registry.
|
136
|
+
* @param node The node to update.
|
137
|
+
* @param key The key to set.
|
138
|
+
* @param value The text data value to set.
|
139
|
+
*/
|
140
|
+
function setText(bytes32 node, string key, string value) public only_owner(node) {
|
141
|
+
records[node].text[key] = value;
|
142
|
+
emit TextChanged(node, key, key);
|
143
|
+
}
|
144
|
+
|
145
|
+
/**
|
146
|
+
* Returns the text data associated with an ENS node and key.
|
147
|
+
* @param node The ENS node to query.
|
148
|
+
* @param key The text data key to query.
|
149
|
+
* @return The associated text data.
|
150
|
+
*/
|
151
|
+
function text(bytes32 node, string key) public view returns (string) {
|
152
|
+
return records[node].text[key];
|
153
|
+
}
|
154
|
+
|
155
|
+
/**
|
156
|
+
* Returns the SECP256k1 public key associated with an ENS node.
|
157
|
+
* Defined in EIP 619.
|
158
|
+
* @param node The ENS node to query
|
159
|
+
* @return x, y the X and Y coordinates of the curve point for the public key.
|
160
|
+
*/
|
161
|
+
function pubkey(bytes32 node) public view returns (bytes32 x, bytes32 y) {
|
162
|
+
return (records[node].pubkey.x, records[node].pubkey.y);
|
163
|
+
}
|
164
|
+
|
165
|
+
/**
|
166
|
+
* Returns the ABI associated with an ENS node.
|
167
|
+
* Defined in EIP205.
|
168
|
+
* @param node The ENS node to query
|
169
|
+
* @param contentTypes A bitwise OR of the ABI formats accepted by the caller.
|
170
|
+
* @return contentType The content type of the return value
|
171
|
+
* @return data The ABI data
|
172
|
+
*/
|
173
|
+
function ABI(bytes32 node, uint256 contentTypes) public view returns (uint256 contentType, bytes data) {
|
174
|
+
Record storage record = records[node];
|
175
|
+
for (contentType = 1; contentType <= contentTypes; contentType <<= 1) {
|
176
|
+
if ((contentType & contentTypes) != 0 && record.abis[contentType].length > 0) {
|
177
|
+
data = record.abis[contentType];
|
178
|
+
return;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
contentType = 0;
|
182
|
+
}
|
183
|
+
|
184
|
+
/**
|
185
|
+
* Returns the name associated with an ENS node, for reverse records.
|
186
|
+
* Defined in EIP181.
|
187
|
+
* @param node The ENS node to query.
|
188
|
+
* @return The associated name.
|
189
|
+
*/
|
190
|
+
function name(bytes32 node) public view returns (string) {
|
191
|
+
return records[node].name;
|
192
|
+
}
|
193
|
+
|
194
|
+
/**
|
195
|
+
* Returns the content hash associated with an ENS node.
|
196
|
+
* Note that this resource type is not standardized, and will likely change
|
197
|
+
* in future to a resource type based on multihash.
|
198
|
+
* @param node The ENS node to query.
|
199
|
+
* @return The associated content hash.
|
200
|
+
*/
|
201
|
+
function content(bytes32 node) public view returns (bytes32) {
|
202
|
+
return records[node].content;
|
203
|
+
}
|
204
|
+
|
205
|
+
/**
|
206
|
+
* Returns the multihash associated with an ENS node.
|
207
|
+
* @param node The ENS node to query.
|
208
|
+
* @return The associated multihash.
|
209
|
+
*/
|
210
|
+
function multihash(bytes32 node) public view returns (bytes) {
|
211
|
+
return records[node].multihash;
|
212
|
+
}
|
213
|
+
|
214
|
+
/**
|
215
|
+
* Returns the address associated with an ENS node.
|
216
|
+
* @param node The ENS node to query.
|
217
|
+
* @return The associated address.
|
218
|
+
*/
|
219
|
+
function addr(bytes32 node) public view returns (address) {
|
220
|
+
return records[node].addr;
|
221
|
+
}
|
222
|
+
|
223
|
+
/**
|
224
|
+
* Returns true if the resolver implements the interface specified by the provided hash.
|
225
|
+
* @param interfaceID The ID of the interface to check for.
|
226
|
+
* @return True if the contract implements the requested interface.
|
227
|
+
*/
|
228
|
+
function supportsInterface(bytes4 interfaceID) public pure returns (bool) {
|
229
|
+
return interfaceID == ADDR_INTERFACE_ID ||
|
230
|
+
interfaceID == CONTENT_INTERFACE_ID ||
|
231
|
+
interfaceID == NAME_INTERFACE_ID ||
|
232
|
+
interfaceID == ABI_INTERFACE_ID ||
|
233
|
+
interfaceID == PUBKEY_INTERFACE_ID ||
|
234
|
+
interfaceID == TEXT_INTERFACE_ID ||
|
235
|
+
interfaceID == MULTIHASH_INTERFACE_ID ||
|
236
|
+
interfaceID == INTERFACE_META_ID;
|
237
|
+
}
|
238
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
pragma solidity ^0.4.24;
|
2
|
+
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @title SafeMath
|
6
|
+
* @dev Math operations with safety checks that throw on error
|
7
|
+
*/
|
8
|
+
library SafeMath {
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @dev Multiplies two numbers, throws on overflow.
|
12
|
+
*/
|
13
|
+
function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
|
14
|
+
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the
|
15
|
+
// benefit is lost if 'b' is also tested.
|
16
|
+
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
|
17
|
+
if (_a == 0) {
|
18
|
+
return 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
c = _a * _b;
|
22
|
+
assert(c / _a == _b);
|
23
|
+
return c;
|
24
|
+
}
|
25
|
+
|
26
|
+
/**
|
27
|
+
* @dev Integer division of two numbers, truncating the quotient.
|
28
|
+
*/
|
29
|
+
function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
|
30
|
+
// assert(_b > 0); // Solidity automatically throws when dividing by 0
|
31
|
+
// uint256 c = _a / _b;
|
32
|
+
// assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
|
33
|
+
return _a / _b;
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
|
38
|
+
*/
|
39
|
+
function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
|
40
|
+
assert(_b <= _a);
|
41
|
+
return _a - _b;
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* @dev Adds two numbers, throws on overflow.
|
46
|
+
*/
|
47
|
+
function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
|
48
|
+
c = _a + _b;
|
49
|
+
assert(c >= _a);
|
50
|
+
return c;
|
51
|
+
}
|
52
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
pragma solidity 0.4.24;
|
2
|
+
|
3
|
+
library SignedSafeMath {
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @dev Adds two int256s and makes sure the result doesn't overflow. Signed
|
7
|
+
* integers aren't supported by the SafeMath library, thus this method
|
8
|
+
* @param _a The first number to be added
|
9
|
+
* @param _a The second number to be added
|
10
|
+
*/
|
11
|
+
function add(int256 _a, int256 _b)
|
12
|
+
internal
|
13
|
+
pure
|
14
|
+
returns (int256)
|
15
|
+
{
|
16
|
+
int256 c = _a + _b;
|
17
|
+
require((_b >= 0 && c >= _a) || (_b < 0 && c < _a), "SignedSafeMath: addition overflow");
|
18
|
+
|
19
|
+
return c;
|
20
|
+
}
|
21
|
+
}
|