From 7d749e2aed1604fc4e64e725f6b205b68817e189 Mon Sep 17 00:00:00 2001 From: brioux Date: Sun, 26 Mar 2023 10:56:20 -0600 Subject: [PATCH] Hedera contract deployment Modify hardhat/hedera deploy scripts and README Signed-off-by: brioux --- app/api-server/server.ts | 2 +- app/frontend/contracts/src/addresses.ts | 24 +- hardhat/.ethereum-config.js.template | 6 +- hardhat/deployments/hedera-testnet/.chainId | 1 + .../deployments/hedera-testnet/DAOToken.json | 1001 +++++++++++++ .../deployments/hedera-testnet/Timelock.json | 538 +++++++ .../303f0d0861904a4ebaa538b95b45b55f.json | 35 + .../9cae68ccb2da1ec502699fbdf8934a04.json | 98 ++ hardhat/hardhat.config.ts | 41 +- hardhat/hedera/README.md | 81 +- hardhat/hedera/deploy.js | 157 +- hardhat/hedera/package-lock.json | 1278 +++++++++++++++++ 12 files changed, 3164 insertions(+), 98 deletions(-) create mode 100644 hardhat/deployments/hedera-testnet/.chainId create mode 100644 hardhat/deployments/hedera-testnet/DAOToken.json create mode 100644 hardhat/deployments/hedera-testnet/Timelock.json create mode 100644 hardhat/deployments/hedera-testnet/solcInputs/303f0d0861904a4ebaa538b95b45b55f.json create mode 100644 hardhat/deployments/hedera-testnet/solcInputs/9cae68ccb2da1ec502699fbdf8934a04.json create mode 100644 hardhat/hedera/package-lock.json diff --git a/app/api-server/server.ts b/app/api-server/server.ts index f216fc578..28140fa52 100644 --- a/app/api-server/server.ts +++ b/app/api-server/server.ts @@ -26,7 +26,7 @@ const assertEnv = (key: string): string => { return process.env[key] || ''; } const contract_address = assertEnv('LEDGER_EMISSION_TOKEN_CONTRACT_ADDRESS') -const tracker_address = process.env['LEDGER_CARBON_TRACKER_ADDRESS'] +const tracker_address = assertEnv('LEDGER_CARBON_TRACKER_ADDRESS') const network_name = assertEnv('LEDGER_ETH_NETWORK') const network_rpc_url = assertEnv('LEDGER_ETH_JSON_RPC_URL') const network_ws_url = process.env['LEDGER_ETH_WS_URL'] diff --git a/app/frontend/contracts/src/addresses.ts b/app/frontend/contracts/src/addresses.ts index 90a17d08d..439580857 100644 --- a/app/frontend/contracts/src/addresses.ts +++ b/app/frontend/contracts/src/addresses.ts @@ -21,6 +21,24 @@ const networksAndAddresses = { } }, + hedera_testnet: { + network: "Hedera Testnet", + tokenNetwork: { + address: "0x00000000000000000000000000000000003be83f", + }, + carbonTracker: { + address: "0x00000000000000000000000000000000003c0064", + }, + dao: { + governor: { + address: "", + }, + daoToken: { + address: "", + } + } + }, + goerli: { network: "Goerli Testnet", tokenNetwork: { @@ -34,10 +52,10 @@ const networksAndAddresses = { }, dao: { governor: { - address: "0x9F4590684d1DD950dF65Dc71D39f782bc3af317A", + address: "0x6875735ee7864673B211eC2ec2a534179F863DAD", }, daoToken: { - address: "0x67E5b82809f28aA321818b90bF5c603D954f87C8", + address: "0x08AA8Ae1E7A087b591a5a1234fBE20e592c5c417", } } }, @@ -152,6 +170,6 @@ const networksAndAddresses = { } // change this to the network you want -const addresses = networksAndAddresses.hardhat; +const addresses = networksAndAddresses.hedera_testnet; export default addresses; diff --git a/hardhat/.ethereum-config.js.template b/hardhat/.ethereum-config.js.template index 949d02204..71f3f046e 100644 --- a/hardhat/.ethereum-config.js.template +++ b/hardhat/.ethereum-config.js.template @@ -18,4 +18,8 @@ exports.ETHERSCAN_API_KEY = ""; exports.BSC_PRIVATE_KEY = ""; // Only required for Avalanche deployments -exports.AVALANCHE_PRIVATE_KEY = "" +exports.AVALANCHE_PRIVATE_KEY = ""; + +// Only required for Hedera Testnet deployments +exports.HEDERA_TESTNET_ENDPOINT = ""; +exports.HEDERA_TESTNET_OPERATOR_PRIVATE_KEY = ""; diff --git a/hardhat/deployments/hedera-testnet/.chainId b/hardhat/deployments/hedera-testnet/.chainId new file mode 100644 index 000000000..fb32aea38 --- /dev/null +++ b/hardhat/deployments/hedera-testnet/.chainId @@ -0,0 +1 @@ +296 \ No newline at end of file diff --git a/hardhat/deployments/hedera-testnet/DAOToken.json b/hardhat/deployments/hedera-testnet/DAOToken.json new file mode 100644 index 000000000..e4e494234 --- /dev/null +++ b/hardhat/deployments/hedera-testnet/DAOToken.json @@ -0,0 +1,1001 @@ +{ + "address": "0xbF2d063fcb49Ae3Ac530cea715720e6a95be4B1E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "_burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "_lockTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "addToTotalSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "fromBlock", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getCurrentVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInitialHolder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getPriorVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialHolder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "setGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x7bf7ef5faf07d2b3390a1a23d1df935c9f21f02210583acef03c35b18afa4c45", + "receipt": { + "to": "0x00000000000000000000000000000000003BD936", + "from": "0x000000000000000000000000000000000037f97F", + "contractAddress": "0xbF2d063fcb49Ae3Ac530cea715720e6a95be4B1E", + "transactionIndex": 4, + "gasUsed": "320000", + "logsBloom": "0x00000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000020000000000000000000800000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000040000000000000000000000000004000000000000000000000", + "blockHash": "0x35983c06aac8c74a3c28af338273587e3d555c7ef1676488c59f3c18ccb5b4ee", + "transactionHash": "0x7bf7ef5faf07d2b3390a1a23d1df935c9f21f02210583acef03c35b18afa4c45", + "logs": [ + { + "transactionIndex": 4, + "blockNumber": 2543741, + "transactionHash": "0x7bf7ef5faf07d2b3390a1a23d1df935c9f21f02210583acef03c35b18afa4c45", + "address": "0xbF2d063fcb49Ae3Ac530cea715720e6a95be4B1E", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000082c12df8ea6197a37fc801f16e71b7b86a457d1c" + ], + "data": "0x000000000000000000000000000000000000000000084595161401484a000000", + "logIndex": 0, + "blockHash": "0x35983c06aac8c74a3c28af338273587e3d555c7ef1676488c59f3c18ccb5b4ee" + } + ], + "blockNumber": 2543741, + "cumulativeGasUsed": "320000", + "status": 1, + "byzantium": true + }, + "args": [ + "0x82c12DF8ea6197A37Fc801F16E71b7b86A457d1C" + ], + "numDeployments": 4, + "solcInputHash": "303f0d0861904a4ebaa538b95b45b55f", + "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"_burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"_lockTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"addToTotalSupply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"rawAmount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"fromBlock\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"votes\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getCurrentVotes\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInitialHolder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getPriorVotes\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialHolder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"setGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"rawAmount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"rawAmount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"params\":{\"account\":\"The address of the account holding the funds\",\"spender\":\"The address of the account spending the funds\"},\"returns\":{\"_0\":\"The number of tokens approved\"}},\"approve(address,uint256)\":{\"details\":\"This will overwrite the approval amount for `spender` and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\",\"params\":{\"rawAmount\":\"The number of tokens that are approved (2^256-1 means infinite)\",\"spender\":\"The address of the account which may transfer tokens\"},\"returns\":{\"_0\":\"Whether or not the approval succeeded\"}},\"balanceOf(address)\":{\"params\":{\"account\":\"The address of the account to get the balance of\"},\"returns\":{\"_0\":\"The number of tokens held\"}},\"constructor\":{\"params\":{\"account\":\"The initial account to grant all the tokens\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\",\"expiry\":\"The time at which to expire the signature\",\"nonce\":\"The contract state required to match the signature\",\"r\":\"Half of the ECDSA signature pair\",\"s\":\"Half of the ECDSA signature pair\",\"v\":\"The recovery byte of the signature\"}},\"getCurrentVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"returns\":{\"_0\":\"The number of current votes for `account`\"}},\"getPriorVotes(address,uint256)\":{\"details\":\"Block number must be a finalized block or else this function will revert to prevent misinformation.\",\"params\":{\"account\":\"The address of the account to check\",\"blockNumber\":\"The block number to get the vote balance at\"},\"returns\":{\"_0\":\"The number of votes the account had as of the given block\"}},\"transfer(address,uint256)\":{\"params\":{\"dst\":\"The address of the destination account\",\"rawAmount\":\"The number of tokens to transfer\"},\"returns\":{\"_0\":\"Whether or not the transfer succeeded\"}},\"transferFrom(address,address,uint256)\":{\"params\":{\"dst\":\"The address of the destination account\",\"rawAmount\":\"The number of tokens to transfer\",\"src\":\"The address of the source account\"},\"returns\":{\"_0\":\"Whether or not the transfer succeeded\"}}},\"stateVariables\":{\"allowances\":{\"details\":\"Allowance amounts on behalf of others\"},\"balances\":{\"details\":\"Official record of token balances for each account\"}},\"version\":1},\"userdoc\":{\"events\":{\"Approval(address,address,uint256)\":{\"notice\":\"The standard EIP-20 approval event\"},\"DelegateChanged(address,address,address)\":{\"notice\":\"An event thats emitted when an account changes its delegate\"},\"DelegateVotesChanged(address,uint256,uint256)\":{\"notice\":\"An event thats emitted when a delegate account's vote balance changes\"},\"Transfer(address,address,uint256)\":{\"notice\":\"The standard EIP-20 transfer event\"}},\"kind\":\"user\",\"methods\":{\"DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the delegation struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"allowance(address,address)\":{\"notice\":\"Get the number of tokens `spender` is approved to spend on behalf of `account`\"},\"approve(address,uint256)\":{\"notice\":\"Approve `spender` to transfer up to `amount` from `src`\"},\"balanceOf(address)\":{\"notice\":\"Get the number of tokens held by the `account`\"},\"checkpoints(address,uint32)\":{\"notice\":\"A record of votes checkpoints for each account, by index\"},\"constructor\":{\"notice\":\"Construct a new dCLM8 token\"},\"decimals()\":{\"notice\":\"EIP-20 token decimals for this token\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"Delegates votes from signatory to `delegatee`\"},\"delegates(address)\":{\"notice\":\"A record of each accounts delegate\"},\"getCurrentVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"getPriorVotes(address,uint256)\":{\"notice\":\"Determine the prior number of votes for an account as of a block number\"},\"governor()\":{\"notice\":\"Governor to be set after deploy for permissions to burn tokens (only set once)\"},\"initialHolder()\":{\"notice\":\"Initial holder of all DAO tokens\"},\"name()\":{\"notice\":\"EIP-20 token name for this token\"},\"nonces(address)\":{\"notice\":\"A record of states for signing / validating signatures\"},\"numCheckpoints(address)\":{\"notice\":\"The number of checkpoints for each account\"},\"symbol()\":{\"notice\":\"EIP-20 token symbol for this token\"},\"totalSupply()\":{\"notice\":\"Total number of tokens in circulation\"},\"transfer(address,uint256)\":{\"notice\":\"Transfer `amount` tokens from `msg.sender` to `dst`\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"Transfer `amount` tokens from `src` to `dst`\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Governance/DAOToken.sol\":\"DAOToken\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"solidity/Governance/DAOToken.sol\":{\"content\":\"pragma solidity ^0.8.0;\\npragma experimental ABIEncoderV2;\\n\\n// SPDX-License-Identifier: BSD-3-Clause\\n\\n/* Copyright 2021 Compound Labs, Inc.\\nRedistribution and use in source and binary forms, with or without\\nmodification, are permitted provided that the following conditions are met:\\n1. Redistributions of source code must retain the above copyright notice, this\\nlist of conditions and the following disclaimer.\\n2. Redistributions in binary form must reproduce the above copyright notice,\\nthis list of conditions and the following disclaimer in the documentation\\nand/or other materials provided with the distribution.\\n3. Neither the name of the copyright holder nor the names of its contributors\\nmay be used to endorse or promote products derived from this software without\\nspecific prior written permission.\\n\\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \\\"AS IS\\\" AND\\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */\\n\\n// Original work from Compound: https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol\\n// Modified to work in the NetEmissionsTokenNetwork system\\n\\ncontract DAOToken {\\n /// @notice EIP-20 token name for this token\\n string public constant name = \\\"Climate DAO Token\\\";\\n\\n /// @notice EIP-20 token symbol for this token\\n string public constant symbol = \\\"dCLM8\\\";\\n\\n /// @notice EIP-20 token decimals for this token\\n uint8 public constant decimals = 18;\\n\\n /// @notice Total number of tokens in circulation\\n uint256 public totalSupply = 10000000e18; // 10 million dCLM8\\n\\n /// @notice Initial holder of all DAO tokens\\n address public initialHolder;\\n\\n /// @notice Governor to be set after deploy for permissions to burn tokens (only set once)\\n address public governor = address(0);\\n\\n /// @dev Allowance amounts on behalf of others\\n mapping(address => mapping(address => uint96)) internal allowances;\\n\\n /// @dev Official record of token balances for each account\\n mapping(address => uint96) internal balances;\\n\\n /// @notice A record of each accounts delegate\\n mapping(address => address) public delegates;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH =\\n keccak256(\\n \\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\"\\n );\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH =\\n keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint256) public nonces;\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChanged(\\n address indexed delegator,\\n address indexed fromDelegate,\\n address indexed toDelegate\\n );\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChanged(\\n address indexed delegate,\\n uint256 previousBalance,\\n uint256 newBalance\\n );\\n\\n /// @notice The standard EIP-20 transfer event\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @notice The standard EIP-20 approval event\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 amount\\n );\\n\\n /**\\n * @notice Construct a new dCLM8 token\\n * @param account The initial account to grant all the tokens\\n */\\n constructor(address account) {\\n balances[account] = uint96(totalSupply);\\n initialHolder = account;\\n emit Transfer(address(0), account, totalSupply);\\n }\\n\\n /**\\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\\n * @param account The address of the account holding the funds\\n * @param spender The address of the account spending the funds\\n * @return The number of tokens approved\\n */\\n function allowance(address account, address spender)\\n external\\n view\\n returns (uint256)\\n {\\n return allowances[account][spender];\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n function approve(address spender, uint256 rawAmount)\\n external\\n returns (bool)\\n {\\n uint96 amount;\\n if (rawAmount == type(uint256).max) {\\n amount = type(uint96).max;\\n } else {\\n amount = safe96(\\n rawAmount,\\n \\\"dCLM8::approve: amount exceeds 96 bits\\\"\\n );\\n }\\n\\n allowances[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the number of tokens held by the `account`\\n * @param account The address of the account to get the balance of\\n * @return The number of tokens held\\n */\\n function balanceOf(address account) external view returns (uint256) {\\n return balances[account];\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transfer(address dst, uint256 rawAmount) external returns (bool) {\\n if ((msg.sender != initialHolder) && (msg.sender != governor)) {\\n revert(\\n \\\"dCLM8::transfer: sender must be initial holder or DAO governor\\\"\\n );\\n }\\n\\n uint96 amount = safe96(\\n rawAmount,\\n \\\"dCLM8::transfer: amount exceeds 96 bits\\\"\\n );\\n _transferTokens(msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param rawAmount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 rawAmount\\n ) external returns (bool) {\\n if ((src != initialHolder) && (src != governor)) {\\n revert(\\n \\\"dCLM8::transfer: sender must be initial holder or DAO governor\\\"\\n );\\n }\\n\\n address spender = msg.sender;\\n uint96 spenderAllowance = allowances[src][spender];\\n uint96 amount = safe96(\\n rawAmount,\\n \\\"dCLM8::approve: amount exceeds 96 bits\\\"\\n );\\n\\n if (spender != src && spenderAllowance != type(uint96).max) {\\n uint96 newAllowance = sub96(\\n spenderAllowance,\\n amount,\\n \\\"dCLM8::transferFrom: transfer amount exceeds spender allowance\\\"\\n );\\n allowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n }\\n\\n _transferTokens(src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) public {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(\\n address delegatee,\\n uint256 nonce,\\n uint256 expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(\\n DOMAIN_TYPEHASH,\\n keccak256(bytes(name)),\\n getChainId(),\\n address(this)\\n )\\n );\\n bytes32 structHash = keccak256(\\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\\n );\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash)\\n );\\n address signatory = ecrecover(digest, v, r, s);\\n require(\\n signatory != address(0),\\n \\\"dCLM8::delegateBySig: invalid signature\\\"\\n );\\n require(\\n nonce == nonces[signatory]++,\\n \\\"dCLM8::delegateBySig: invalid nonce\\\"\\n );\\n require(\\n block.timestamp <= expiry,\\n \\\"dCLM8::delegateBySig: signature expired\\\"\\n );\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return\\n nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n /**\\n * @notice Determine the prior number of votes for an account as of a block number\\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The number of votes the account had as of the given block\\n */\\n function getPriorVotes(address account, uint256 blockNumber)\\n public\\n view\\n returns (uint96)\\n {\\n require(\\n blockNumber < block.number,\\n \\\"dCLM8::getPriorVotes: not yet determined\\\"\\n );\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n function _burn(address account, uint96 amount) external {\\n require(\\n account != address(0),\\n \\\"dCLM8::_burn: burn from the zero address\\\"\\n );\\n require(msg.sender == governor, \\\"dCLM8::_burn: must be governor\\\");\\n\\n uint96 accountBalance = balances[account];\\n require(\\n accountBalance >= amount,\\n \\\"dCLM8::_burn: burn amount exceeds balance\\\"\\n );\\n balances[account] = accountBalance - amount;\\n totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = balances[delegator];\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChanged(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _transferTokens(\\n address src,\\n address dst,\\n uint96 amount\\n ) internal {\\n require(\\n src != address(0),\\n \\\"dCLM8::_transferTokens: cannot transfer from the zero address\\\"\\n );\\n require(\\n dst != address(0),\\n \\\"dCLM8::_transferTokens: cannot transfer to the zero address\\\"\\n );\\n\\n balances[src] = sub96(\\n balances[src],\\n amount,\\n \\\"dCLM8::_transferTokens: transfer amount exceeds balance\\\"\\n );\\n balances[dst] = add96(\\n balances[dst],\\n amount,\\n \\\"dCLM8::_transferTokens: transfer amount overflows\\\"\\n );\\n emit Transfer(src, dst, amount);\\n\\n // If dst address has no delgatees, automatically set to self. Otherwise, transfer to dst's delegates\\n if (delegates[dst] == address(0)) {\\n _delegate(dst, dst);\\n } else {\\n _moveDelegates(delegates[src], delegates[dst], amount);\\n }\\n }\\n\\n function _lockTokens(address src, uint96 amount) external {\\n require(msg.sender == governor, \\\"dCLM8::lockTokens: must be governor\\\");\\n\\n balances[src] = sub96(\\n balances[src],\\n amount,\\n \\\"dCLM8::_transferTokens: transfer amount exceeds balance\\\"\\n );\\n balances[governor] = add96(\\n balances[governor],\\n amount,\\n \\\"dCLM8::_transferTokens: transfer amount overflows\\\"\\n );\\n\\n emit Transfer(src, governor, amount);\\n }\\n\\n function _moveDelegates(\\n address srcRep,\\n address dstRep,\\n uint96 amount\\n ) internal {\\n if (srcRep != dstRep && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0\\n ? checkpoints[srcRep][srcRepNum - 1].votes\\n : 0;\\n uint96 srcRepNew = sub96(\\n srcRepOld,\\n amount,\\n \\\"dCLM8::_moveVotes: vote amount underflows\\\"\\n );\\n _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint96 dstRepOld = dstRepNum > 0\\n ? checkpoints[dstRep][dstRepNum - 1].votes\\n : 0;\\n uint96 dstRepNew = add96(\\n dstRepOld,\\n amount,\\n \\\"dCLM8::_moveVotes: vote amount overflows\\\"\\n );\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(\\n address delegatee,\\n uint32 nCheckpoints,\\n uint96 oldVotes,\\n uint96 newVotes\\n ) internal {\\n uint32 blockNumber = safe32(\\n block.number,\\n \\\"dCLM8::_writeCheckpoint: block number exceeds 32 bits\\\"\\n );\\n\\n if (\\n nCheckpoints > 0 &&\\n checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber\\n ) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(\\n blockNumber,\\n newVotes\\n );\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage)\\n internal\\n pure\\n returns (uint32)\\n {\\n require(n < 2**32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint256 n, string memory errorMessage)\\n internal\\n pure\\n returns (uint96)\\n {\\n require(n < 2**96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(\\n uint96 a,\\n uint96 b,\\n string memory errorMessage\\n ) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(\\n uint96 a,\\n uint96 b,\\n string memory errorMessage\\n ) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal view returns (uint256) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n return chainId;\\n }\\n\\n function addToTotalSupply(uint256 amount) public {\\n if ((msg.sender != initialHolder) && (msg.sender != governor)) {\\n revert(\\n \\\"dCLM8::addToTotalSupply: must be initial holder or DAO governor\\\"\\n );\\n }\\n uint96 _amount = safe96(\\n amount,\\n \\\"dCLM8::addToTotalSupply: amount exceeds 96 bits\\\"\\n );\\n balances[msg.sender] = add96(\\n balances[msg.sender],\\n _amount,\\n \\\"dCLM8::addToTotalSupply: amount overflows\\\"\\n );\\n totalSupply += amount;\\n // also need to sync the delegate checkpoint\\n _moveDelegates(address(0), msg.sender, _amount);\\n }\\n\\n function getTotalSupply() external view returns (uint256) {\\n return totalSupply;\\n }\\n\\n function getInitialHolder() external view returns (address) {\\n return initialHolder;\\n }\\n\\n function setGovernor(address newGovernor) public {\\n require(\\n msg.sender == initialHolder,\\n \\\"dCLM8::setGovernor: must be initial holder\\\"\\n );\\n governor = newGovernor;\\n }\\n}\\n\",\"keccak256\":\"0x1bd2aa8e899b4aa7eb1ce7b8e4d1db5d6b20388de9992f37b16acf842e6099f3\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60806040526a084595161401484a000000600055600280546001600160a01b031916905534801561002f57600080fd5b506040516121d33803806121d383398101604081905261004e916100d6565b600080546001600160a01b03831680835260046020908152604080852080546001600160601b0319166001600160601b0390951694909417909355600180546001600160a01b03191683179055835492519283529092917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350610104565b6000602082840312156100e7578081fd5b81516001600160a01b03811681146100fd578182fd5b9392505050565b6120c0806101136000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806372d3ee9e116100f9578063b72218e311610097578063c4e41b2211610071578063c4e41b2214610451578063dd62ed3e14610459578063e7a324dc1461049b578063f1127ed8146104c2576101a9565b8063b72218e314610418578063c3cda5201461042b578063c42cf5351461043e576101a9565b806395d89b41116100d357806395d89b41146103bd578063a9059cbb146103e1578063ae80d9de146103f4578063b4b5ea5714610405576101a9565b806372d3ee9e1461035f578063782d6fe1146103725780637ecebe001461039d576101a9565b806328ce884511610166578063587cde1e11610140578063587cde1e146102d55780635c19a95c146102fe5780636fcfff451461031157806370a082311461034c576101a9565b806328ce884514610293578063313ce567146102a85780633b2d52ac146102c2576101a9565b806306fdde03146101ae578063095ea7b3146101f45780630c340a241461021757806318160ddd1461024257806320606b701461025957806323b872dd14610280575b600080fd5b6101de6040518060400160405280601181526020017021b634b6b0ba32902220a7902a37b5b2b760791b81525081565b6040516101eb9190611ceb565b60405180910390f35b610207610202366004611bd8565b610529565b60405190151581526020016101eb565b60025461022a906001600160a01b031681565b6040516001600160a01b0390911681526020016101eb565b61024b60005481565b6040519081526020016101eb565b61024b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b61020761028e366004611b9d565b6105ea565b6102a66102a1366004611cd3565b610782565b005b6102b0601281565b60405160ff90911681526020016101eb565b6102a66102d0366004611c9d565b6108db565b61022a6102e3366004611b51565b6005602052600090815260409020546001600160a01b031681565b6102a661030c366004611b51565b610a71565b61033761031f366004611b51565b60076020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101eb565b61024b61035a366004611b51565b610a7e565b6102a661036d366004611c9d565b610aa6565b610385610380366004611bd8565b610c92565b6040516001600160601b0390911681526020016101eb565b61024b6103ab366004611b51565b60086020526000908152604090205481565b6101de604051806040016040528060058152602001640c886989a760db1b81525081565b6102076103ef366004611bd8565b610f1a565b6001546001600160a01b031661022a565b610385610413366004611b51565b610f9b565b60015461022a906001600160a01b031681565b6102a6610439366004611c01565b611019565b6102a661044c366004611b51565b611311565b60005461024b565b61024b610467366004611b6b565b6001600160a01b0391821660009081526003602090815260408083209390941682529190915220546001600160601b031690565b61024b7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b6105056104d0366004611c5f565b600660209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6040805163ffffffff90931683526001600160601b039091166020830152016101eb565b60008060001983141561054457506001600160601b03610569565b61056683604051806060016040528060268152602001612007602691396113a0565b90505b3360008181526003602090815260408083206001600160a01b0389168085529083529281902080546001600160601b0319166001600160601b03871690811790915590519081529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a360019150505b92915050565b6001546000906001600160a01b0385811691161480159061061957506002546001600160a01b03858116911614155b1561063f5760405162461bcd60e51b815260040161063690611d3e565b60405180910390fd5b6001600160a01b03841660009081526003602090815260408083203380855290835281842054825160608101909352602680845291946001600160601b03909116939092610695928892612007908301396113a0565b9050866001600160a01b0316836001600160a01b0316141580156106c257506001600160601b0382811614155b1561076a5760006106ec83836040518060600160405280603e8152602001611fc9603e91396113cf565b6001600160a01b038981166000818152600360209081526040808320948a168084529482529182902080546001600160601b0319166001600160601b0387169081179091559151918252939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b610775878783611419565b5060019695505050505050565b6001546001600160a01b031633148015906107a857506002546001600160a01b03163314155b1561081b5760405162461bcd60e51b815260206004820152603f60248201527f64434c4d383a3a616464546f546f74616c537570706c793a206d75737420626560448201527f20696e697469616c20686f6c646572206f722044414f20676f7665726e6f72006064820152608401610636565b600061083f826040518060600160405280602f8152602001611f73602f91396113a0565b33600090815260046020908152604091829020548251606081019093526029808452939450610885936001600160601b03909116928592909190611f4a90830139611698565b33600090815260046020526040812080546001600160601b0319166001600160601b039390931692909217909155805483919081906108c5908490611d9b565b909155506108d79050600033836116e5565b5050565b6002546001600160a01b031633146109415760405162461bcd60e51b815260206004820152602360248201527f64434c4d383a3a6c6f636b546f6b656e733a206d75737420626520676f7665726044820152623737b960e91b6064820152608401610636565b6001600160a01b03821660009081526004602090815260409182902054825160608101909352603780845261098c936001600160601b039092169285929190611ee2908301396113cf565b6001600160a01b03838116600090815260046020908152604080832080546001600160601b0319166001600160601b039687161790556002549093168252908290205482516060810190935260318084526109f79491909116928592909190611f1990830139611698565b600280546001600160a01b0390811660009081526004602090815260409182902080546001600160601b0319166001600160601b03968716179055925490519385168452811692908516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b610a7b3382611891565b50565b6001600160a01b0381166000908152600460205260409020546001600160601b03165b919050565b6001600160a01b038216610b0d5760405162461bcd60e51b815260206004820152602860248201527f64434c4d383a3a5f6275726e3a206275726e2066726f6d20746865207a65726f604482015267206164647265737360c01b6064820152608401610636565b6002546001600160a01b03163314610b675760405162461bcd60e51b815260206004820152601e60248201527f64434c4d383a3a5f6275726e3a206d75737420626520676f7665726e6f7200006044820152606401610636565b6001600160a01b0382166000908152600460205260409020546001600160601b03908116908216811015610bef5760405162461bcd60e51b815260206004820152602960248201527f64434c4d383a3a5f6275726e3a206275726e20616d6f756e7420657863656564604482015268732062616c616e636560b81b6064820152608401610636565b610bf98282611e68565b6001600160a01b038416600090815260046020526040812080546001600160601b0319166001600160601b039384161790558054918416918190610c3e908490611e2c565b90915550506040516001600160601b03831681526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6000438210610cf45760405162461bcd60e51b815260206004820152602860248201527f64434c4d383a3a6765745072696f72566f7465733a206e6f74207965742064656044820152671d195c9b5a5b995960c21b6064820152608401610636565b6001600160a01b03831660009081526007602052604090205463ffffffff1680610d225760009150506105e4565b6001600160a01b03841660009081526006602052604081208491610d47600185611e43565b63ffffffff90811682526020820192909252604001600020541611610dba576001600160a01b038416600090815260066020526040812090610d8a600184611e43565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b031691506105e49050565b6001600160a01b038416600090815260066020908152604080832083805290915290205463ffffffff16831015610df55760009150506105e4565b600080610e03600184611e43565b90505b8163ffffffff168163ffffffff161115610ed55760006002610e288484611e43565b610e329190611dfd565b610e3c9083611e43565b6001600160a01b038816600090815260066020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b031691810191909152919250871415610ea9576020015194506105e49350505050565b805163ffffffff16871115610ec057819350610ece565b610ecb600183611e43565b92505b5050610e06565b506001600160a01b038516600090815260066020908152604080832063ffffffff909416835292905220546001600160601b03600160201b9091041691505092915050565b6001546000906001600160a01b03163314801590610f4357506002546001600160a01b03163314155b15610f605760405162461bcd60e51b815260040161063690611d3e565b6000610f8483604051806060016040528060278152602001611fa2602791396113a0565b9050610f91338583611419565b5060019392505050565b6001600160a01b03811660009081526007602052604081205463ffffffff1680610fc6576000611012565b6001600160a01b038316600090815260066020526040812090610fea600184611e43565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03165b9392505050565b604080518082018252601181527021b634b6b0ba32902220a7902a37b5b2b760791b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527f7c75c83381dcf4c0e5ba36df2cc653b50dcd8f69236256411bc04c9f677ed4c081840152466060820152306080808301919091528351808303909101815260a0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c08301526001600160a01b038a1660e083015261010082018990526101208083018990528451808403909101815261014083019094528351939092019290922061190160f01b6101608401526101628301829052610182830181905290916000906101a20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa1580156111a5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166112185760405162461bcd60e51b815260206004820152602760248201527f64434c4d383a3a64656c656761746542795369673a20696e76616c6964207369604482015266676e617475726560c81b6064820152608401610636565b6001600160a01b038116600090815260086020526040812080549161123c83611e88565b91905055891461129a5760405162461bcd60e51b815260206004820152602360248201527f64434c4d383a3a64656c656761746542795369673a20696e76616c6964206e6f6044820152626e636560e81b6064820152608401610636565b874211156112fa5760405162461bcd60e51b815260206004820152602760248201527f64434c4d383a3a64656c656761746542795369673a207369676e617475726520604482015266195e1c1a5c995960ca1b6064820152608401610636565b611304818b611891565b505050505b505050505050565b6001546001600160a01b0316331461137e5760405162461bcd60e51b815260206004820152602a60248201527f64434c4d383a3a736574476f7665726e6f723a206d75737420626520696e697460448201526934b0b6103437b63232b960b11b6064820152608401610636565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600081600160601b84106113c75760405162461bcd60e51b81526004016106369190611ceb565b509192915050565b6000836001600160601b0316836001600160601b0316111582906114065760405162461bcd60e51b81526004016106369190611ceb565b506114118385611e68565b949350505050565b6001600160a01b0383166114955760405162461bcd60e51b815260206004820152603d60248201527f64434c4d383a3a5f7472616e73666572546f6b656e733a2063616e6e6f74207460448201527f72616e736665722066726f6d20746865207a65726f20616464726573730000006064820152608401610636565b6001600160a01b0382166115115760405162461bcd60e51b815260206004820152603b60248201527f64434c4d383a3a5f7472616e73666572546f6b656e733a2063616e6e6f74207460448201527f72616e7366657220746f20746865207a65726f206164647265737300000000006064820152608401610636565b6001600160a01b03831660009081526004602090815260409182902054825160608101909352603780845261155c936001600160601b039092169285929190611ee2908301396113cf565b6001600160a01b03848116600090815260046020908152604080832080546001600160601b0319166001600160601b039687161790559286168252908290205482516060810190935260318084526115c49491909116928592909190611f1990830139611698565b6001600160a01b0383811660008181526004602090815260409182902080546001600160601b0319166001600160601b03968716179055905193851684529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36001600160a01b03828116600090815260056020526040902054166116615761165c8283611891565b611693565b6001600160a01b03808416600090815260056020526040808220548584168352912054611693929182169116836116e5565b505050565b6000806116a58486611ddb565b9050846001600160601b0316816001600160601b0316101583906116dc5760405162461bcd60e51b81526004016106369190611ceb565b50949350505050565b816001600160a01b0316836001600160a01b03161415801561171057506000816001600160601b0316115b15611693576001600160a01b038316156117d5576001600160a01b03831660009081526007602052604081205463ffffffff16908161175057600061179c565b6001600160a01b038516600090815260066020526040812090611774600185611e43565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03165b905060006117c3828560405180606001604052806029815260200161202d602991396113cf565b90506117d18684848461191b565b5050505b6001600160a01b03821615611693576001600160a01b03821660009081526007602052604081205463ffffffff16908161181057600061185c565b6001600160a01b038416600090815260066020526040812090611834600185611e43565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03165b905060006118838285604051806060016040528060288152602001611eba60289139611698565b90506113098584848461191b565b6001600160a01b03808316600081815260056020818152604080842080546004845282862054949093528787166001600160a01b031984168117909155905191909516946001600160601b039092169391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46119158284836116e5565b50505050565b600061193f4360405180606001604052806035815260200161205660359139611b13565b905060008463ffffffff1611801561199957506001600160a01b038516600090815260066020526040812063ffffffff83169161197d600188611e43565b63ffffffff908116825260208201929092526040016000205416145b15611a0d576001600160a01b038516600090815260066020526040812083916119c3600188611e43565b63ffffffff168152602081019190915260400160002080546001600160601b0392909216600160201b026fffffffffffffffffffffffff0000000019909216919091179055611abe565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000908152600682528681208b8616825290915294909420925183549451909116600160201b026fffffffffffffffffffffffffffffffff19909416911617919091179055611a8d846001611db3565b6001600160a01b0386166000908152600760205260409020805463ffffffff191663ffffffff929092169190911790555b604080516001600160601b038086168252841660208201526001600160a01b038716917fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724910160405180910390a25050505050565b600081600160201b84106113c75760405162461bcd60e51b81526004016106369190611ceb565b80356001600160a01b0381168114610aa157600080fd5b600060208284031215611b62578081fd5b61101282611b3a565b60008060408385031215611b7d578081fd5b611b8683611b3a565b9150611b9460208401611b3a565b90509250929050565b600080600060608486031215611bb1578081fd5b611bba84611b3a565b9250611bc860208501611b3a565b9150604084013590509250925092565b60008060408385031215611bea578182fd5b611bf383611b3a565b946020939093013593505050565b60008060008060008060c08789031215611c19578182fd5b611c2287611b3a565b95506020870135945060408701359350606087013560ff81168114611c45578283fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215611c71578182fd5b611c7a83611b3a565b9150602083013563ffffffff81168114611c92578182fd5b809150509250929050565b60008060408385031215611caf578182fd5b611cb883611b3a565b915060208301356001600160601b0381168114611c92578182fd5b600060208284031215611ce4578081fd5b5035919050565b6000602080835283518082850152825b81811015611d1757858101830151858201604001528201611cfb565b81811115611d285783604083870101525b50601f01601f1916929092016040019392505050565b6020808252603e908201527f64434c4d383a3a7472616e736665723a2073656e646572206d7573742062652060408201527f696e697469616c20686f6c646572206f722044414f20676f7665726e6f720000606082015260800190565b60008219821115611dae57611dae611ea3565b500190565b600063ffffffff808316818516808303821115611dd257611dd2611ea3565b01949350505050565b60006001600160601b03808316818516808303821115611dd257611dd2611ea3565b600063ffffffff80841680611e2057634e487b7160e01b83526012600452602483fd5b92169190910492915050565b600082821015611e3e57611e3e611ea3565b500390565b600063ffffffff83811690831681811015611e6057611e60611ea3565b039392505050565b60006001600160601b0383811690831681811015611e6057611e60611ea3565b6000600019821415611e9c57611e9c611ea3565b5060010190565b634e487b7160e01b600052601160045260246000fdfe64434c4d383a3a5f6d6f7665566f7465733a20766f746520616d6f756e74206f766572666c6f777364434c4d383a3a5f7472616e73666572546f6b656e733a207472616e7366657220616d6f756e7420657863656564732062616c616e636564434c4d383a3a5f7472616e73666572546f6b656e733a207472616e7366657220616d6f756e74206f766572666c6f777364434c4d383a3a616464546f546f74616c537570706c793a20616d6f756e74206f766572666c6f777364434c4d383a3a616464546f546f74616c537570706c793a20616d6f756e742065786365656473203936206269747364434c4d383a3a7472616e736665723a20616d6f756e742065786365656473203936206269747364434c4d383a3a7472616e7366657246726f6d3a207472616e7366657220616d6f756e742065786365656473207370656e64657220616c6c6f77616e636564434c4d383a3a617070726f76653a20616d6f756e742065786365656473203936206269747364434c4d383a3a5f6d6f7665566f7465733a20766f746520616d6f756e7420756e646572666c6f777364434c4d383a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d62657220657863656564732033322062697473a2646970667358221220034b11cf7e6ec37588cc77eb13b439f11d636e9d7a79e87e033390dd0f277c2164736f6c63430008030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c806372d3ee9e116100f9578063b72218e311610097578063c4e41b2211610071578063c4e41b2214610451578063dd62ed3e14610459578063e7a324dc1461049b578063f1127ed8146104c2576101a9565b8063b72218e314610418578063c3cda5201461042b578063c42cf5351461043e576101a9565b806395d89b41116100d357806395d89b41146103bd578063a9059cbb146103e1578063ae80d9de146103f4578063b4b5ea5714610405576101a9565b806372d3ee9e1461035f578063782d6fe1146103725780637ecebe001461039d576101a9565b806328ce884511610166578063587cde1e11610140578063587cde1e146102d55780635c19a95c146102fe5780636fcfff451461031157806370a082311461034c576101a9565b806328ce884514610293578063313ce567146102a85780633b2d52ac146102c2576101a9565b806306fdde03146101ae578063095ea7b3146101f45780630c340a241461021757806318160ddd1461024257806320606b701461025957806323b872dd14610280575b600080fd5b6101de6040518060400160405280601181526020017021b634b6b0ba32902220a7902a37b5b2b760791b81525081565b6040516101eb9190611ceb565b60405180910390f35b610207610202366004611bd8565b610529565b60405190151581526020016101eb565b60025461022a906001600160a01b031681565b6040516001600160a01b0390911681526020016101eb565b61024b60005481565b6040519081526020016101eb565b61024b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b61020761028e366004611b9d565b6105ea565b6102a66102a1366004611cd3565b610782565b005b6102b0601281565b60405160ff90911681526020016101eb565b6102a66102d0366004611c9d565b6108db565b61022a6102e3366004611b51565b6005602052600090815260409020546001600160a01b031681565b6102a661030c366004611b51565b610a71565b61033761031f366004611b51565b60076020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101eb565b61024b61035a366004611b51565b610a7e565b6102a661036d366004611c9d565b610aa6565b610385610380366004611bd8565b610c92565b6040516001600160601b0390911681526020016101eb565b61024b6103ab366004611b51565b60086020526000908152604090205481565b6101de604051806040016040528060058152602001640c886989a760db1b81525081565b6102076103ef366004611bd8565b610f1a565b6001546001600160a01b031661022a565b610385610413366004611b51565b610f9b565b60015461022a906001600160a01b031681565b6102a6610439366004611c01565b611019565b6102a661044c366004611b51565b611311565b60005461024b565b61024b610467366004611b6b565b6001600160a01b0391821660009081526003602090815260408083209390941682529190915220546001600160601b031690565b61024b7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b6105056104d0366004611c5f565b600660209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6040805163ffffffff90931683526001600160601b039091166020830152016101eb565b60008060001983141561054457506001600160601b03610569565b61056683604051806060016040528060268152602001612007602691396113a0565b90505b3360008181526003602090815260408083206001600160a01b0389168085529083529281902080546001600160601b0319166001600160601b03871690811790915590519081529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a360019150505b92915050565b6001546000906001600160a01b0385811691161480159061061957506002546001600160a01b03858116911614155b1561063f5760405162461bcd60e51b815260040161063690611d3e565b60405180910390fd5b6001600160a01b03841660009081526003602090815260408083203380855290835281842054825160608101909352602680845291946001600160601b03909116939092610695928892612007908301396113a0565b9050866001600160a01b0316836001600160a01b0316141580156106c257506001600160601b0382811614155b1561076a5760006106ec83836040518060600160405280603e8152602001611fc9603e91396113cf565b6001600160a01b038981166000818152600360209081526040808320948a168084529482529182902080546001600160601b0319166001600160601b0387169081179091559151918252939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b610775878783611419565b5060019695505050505050565b6001546001600160a01b031633148015906107a857506002546001600160a01b03163314155b1561081b5760405162461bcd60e51b815260206004820152603f60248201527f64434c4d383a3a616464546f546f74616c537570706c793a206d75737420626560448201527f20696e697469616c20686f6c646572206f722044414f20676f7665726e6f72006064820152608401610636565b600061083f826040518060600160405280602f8152602001611f73602f91396113a0565b33600090815260046020908152604091829020548251606081019093526029808452939450610885936001600160601b03909116928592909190611f4a90830139611698565b33600090815260046020526040812080546001600160601b0319166001600160601b039390931692909217909155805483919081906108c5908490611d9b565b909155506108d79050600033836116e5565b5050565b6002546001600160a01b031633146109415760405162461bcd60e51b815260206004820152602360248201527f64434c4d383a3a6c6f636b546f6b656e733a206d75737420626520676f7665726044820152623737b960e91b6064820152608401610636565b6001600160a01b03821660009081526004602090815260409182902054825160608101909352603780845261098c936001600160601b039092169285929190611ee2908301396113cf565b6001600160a01b03838116600090815260046020908152604080832080546001600160601b0319166001600160601b039687161790556002549093168252908290205482516060810190935260318084526109f79491909116928592909190611f1990830139611698565b600280546001600160a01b0390811660009081526004602090815260409182902080546001600160601b0319166001600160601b03968716179055925490519385168452811692908516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b610a7b3382611891565b50565b6001600160a01b0381166000908152600460205260409020546001600160601b03165b919050565b6001600160a01b038216610b0d5760405162461bcd60e51b815260206004820152602860248201527f64434c4d383a3a5f6275726e3a206275726e2066726f6d20746865207a65726f604482015267206164647265737360c01b6064820152608401610636565b6002546001600160a01b03163314610b675760405162461bcd60e51b815260206004820152601e60248201527f64434c4d383a3a5f6275726e3a206d75737420626520676f7665726e6f7200006044820152606401610636565b6001600160a01b0382166000908152600460205260409020546001600160601b03908116908216811015610bef5760405162461bcd60e51b815260206004820152602960248201527f64434c4d383a3a5f6275726e3a206275726e20616d6f756e7420657863656564604482015268732062616c616e636560b81b6064820152608401610636565b610bf98282611e68565b6001600160a01b038416600090815260046020526040812080546001600160601b0319166001600160601b039384161790558054918416918190610c3e908490611e2c565b90915550506040516001600160601b03831681526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6000438210610cf45760405162461bcd60e51b815260206004820152602860248201527f64434c4d383a3a6765745072696f72566f7465733a206e6f74207965742064656044820152671d195c9b5a5b995960c21b6064820152608401610636565b6001600160a01b03831660009081526007602052604090205463ffffffff1680610d225760009150506105e4565b6001600160a01b03841660009081526006602052604081208491610d47600185611e43565b63ffffffff90811682526020820192909252604001600020541611610dba576001600160a01b038416600090815260066020526040812090610d8a600184611e43565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b031691506105e49050565b6001600160a01b038416600090815260066020908152604080832083805290915290205463ffffffff16831015610df55760009150506105e4565b600080610e03600184611e43565b90505b8163ffffffff168163ffffffff161115610ed55760006002610e288484611e43565b610e329190611dfd565b610e3c9083611e43565b6001600160a01b038816600090815260066020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b031691810191909152919250871415610ea9576020015194506105e49350505050565b805163ffffffff16871115610ec057819350610ece565b610ecb600183611e43565b92505b5050610e06565b506001600160a01b038516600090815260066020908152604080832063ffffffff909416835292905220546001600160601b03600160201b9091041691505092915050565b6001546000906001600160a01b03163314801590610f4357506002546001600160a01b03163314155b15610f605760405162461bcd60e51b815260040161063690611d3e565b6000610f8483604051806060016040528060278152602001611fa2602791396113a0565b9050610f91338583611419565b5060019392505050565b6001600160a01b03811660009081526007602052604081205463ffffffff1680610fc6576000611012565b6001600160a01b038316600090815260066020526040812090610fea600184611e43565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03165b9392505050565b604080518082018252601181527021b634b6b0ba32902220a7902a37b5b2b760791b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527f7c75c83381dcf4c0e5ba36df2cc653b50dcd8f69236256411bc04c9f677ed4c081840152466060820152306080808301919091528351808303909101815260a0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c08301526001600160a01b038a1660e083015261010082018990526101208083018990528451808403909101815261014083019094528351939092019290922061190160f01b6101608401526101628301829052610182830181905290916000906101a20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa1580156111a5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166112185760405162461bcd60e51b815260206004820152602760248201527f64434c4d383a3a64656c656761746542795369673a20696e76616c6964207369604482015266676e617475726560c81b6064820152608401610636565b6001600160a01b038116600090815260086020526040812080549161123c83611e88565b91905055891461129a5760405162461bcd60e51b815260206004820152602360248201527f64434c4d383a3a64656c656761746542795369673a20696e76616c6964206e6f6044820152626e636560e81b6064820152608401610636565b874211156112fa5760405162461bcd60e51b815260206004820152602760248201527f64434c4d383a3a64656c656761746542795369673a207369676e617475726520604482015266195e1c1a5c995960ca1b6064820152608401610636565b611304818b611891565b505050505b505050505050565b6001546001600160a01b0316331461137e5760405162461bcd60e51b815260206004820152602a60248201527f64434c4d383a3a736574476f7665726e6f723a206d75737420626520696e697460448201526934b0b6103437b63232b960b11b6064820152608401610636565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600081600160601b84106113c75760405162461bcd60e51b81526004016106369190611ceb565b509192915050565b6000836001600160601b0316836001600160601b0316111582906114065760405162461bcd60e51b81526004016106369190611ceb565b506114118385611e68565b949350505050565b6001600160a01b0383166114955760405162461bcd60e51b815260206004820152603d60248201527f64434c4d383a3a5f7472616e73666572546f6b656e733a2063616e6e6f74207460448201527f72616e736665722066726f6d20746865207a65726f20616464726573730000006064820152608401610636565b6001600160a01b0382166115115760405162461bcd60e51b815260206004820152603b60248201527f64434c4d383a3a5f7472616e73666572546f6b656e733a2063616e6e6f74207460448201527f72616e7366657220746f20746865207a65726f206164647265737300000000006064820152608401610636565b6001600160a01b03831660009081526004602090815260409182902054825160608101909352603780845261155c936001600160601b039092169285929190611ee2908301396113cf565b6001600160a01b03848116600090815260046020908152604080832080546001600160601b0319166001600160601b039687161790559286168252908290205482516060810190935260318084526115c49491909116928592909190611f1990830139611698565b6001600160a01b0383811660008181526004602090815260409182902080546001600160601b0319166001600160601b03968716179055905193851684529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36001600160a01b03828116600090815260056020526040902054166116615761165c8283611891565b611693565b6001600160a01b03808416600090815260056020526040808220548584168352912054611693929182169116836116e5565b505050565b6000806116a58486611ddb565b9050846001600160601b0316816001600160601b0316101583906116dc5760405162461bcd60e51b81526004016106369190611ceb565b50949350505050565b816001600160a01b0316836001600160a01b03161415801561171057506000816001600160601b0316115b15611693576001600160a01b038316156117d5576001600160a01b03831660009081526007602052604081205463ffffffff16908161175057600061179c565b6001600160a01b038516600090815260066020526040812090611774600185611e43565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03165b905060006117c3828560405180606001604052806029815260200161202d602991396113cf565b90506117d18684848461191b565b5050505b6001600160a01b03821615611693576001600160a01b03821660009081526007602052604081205463ffffffff16908161181057600061185c565b6001600160a01b038416600090815260066020526040812090611834600185611e43565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03165b905060006118838285604051806060016040528060288152602001611eba60289139611698565b90506113098584848461191b565b6001600160a01b03808316600081815260056020818152604080842080546004845282862054949093528787166001600160a01b031984168117909155905191909516946001600160601b039092169391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46119158284836116e5565b50505050565b600061193f4360405180606001604052806035815260200161205660359139611b13565b905060008463ffffffff1611801561199957506001600160a01b038516600090815260066020526040812063ffffffff83169161197d600188611e43565b63ffffffff908116825260208201929092526040016000205416145b15611a0d576001600160a01b038516600090815260066020526040812083916119c3600188611e43565b63ffffffff168152602081019190915260400160002080546001600160601b0392909216600160201b026fffffffffffffffffffffffff0000000019909216919091179055611abe565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000908152600682528681208b8616825290915294909420925183549451909116600160201b026fffffffffffffffffffffffffffffffff19909416911617919091179055611a8d846001611db3565b6001600160a01b0386166000908152600760205260409020805463ffffffff191663ffffffff929092169190911790555b604080516001600160601b038086168252841660208201526001600160a01b038716917fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724910160405180910390a25050505050565b600081600160201b84106113c75760405162461bcd60e51b81526004016106369190611ceb565b80356001600160a01b0381168114610aa157600080fd5b600060208284031215611b62578081fd5b61101282611b3a565b60008060408385031215611b7d578081fd5b611b8683611b3a565b9150611b9460208401611b3a565b90509250929050565b600080600060608486031215611bb1578081fd5b611bba84611b3a565b9250611bc860208501611b3a565b9150604084013590509250925092565b60008060408385031215611bea578182fd5b611bf383611b3a565b946020939093013593505050565b60008060008060008060c08789031215611c19578182fd5b611c2287611b3a565b95506020870135945060408701359350606087013560ff81168114611c45578283fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215611c71578182fd5b611c7a83611b3a565b9150602083013563ffffffff81168114611c92578182fd5b809150509250929050565b60008060408385031215611caf578182fd5b611cb883611b3a565b915060208301356001600160601b0381168114611c92578182fd5b600060208284031215611ce4578081fd5b5035919050565b6000602080835283518082850152825b81811015611d1757858101830151858201604001528201611cfb565b81811115611d285783604083870101525b50601f01601f1916929092016040019392505050565b6020808252603e908201527f64434c4d383a3a7472616e736665723a2073656e646572206d7573742062652060408201527f696e697469616c20686f6c646572206f722044414f20676f7665726e6f720000606082015260800190565b60008219821115611dae57611dae611ea3565b500190565b600063ffffffff808316818516808303821115611dd257611dd2611ea3565b01949350505050565b60006001600160601b03808316818516808303821115611dd257611dd2611ea3565b600063ffffffff80841680611e2057634e487b7160e01b83526012600452602483fd5b92169190910492915050565b600082821015611e3e57611e3e611ea3565b500390565b600063ffffffff83811690831681811015611e6057611e60611ea3565b039392505050565b60006001600160601b0383811690831681811015611e6057611e60611ea3565b6000600019821415611e9c57611e9c611ea3565b5060010190565b634e487b7160e01b600052601160045260246000fdfe64434c4d383a3a5f6d6f7665566f7465733a20766f746520616d6f756e74206f766572666c6f777364434c4d383a3a5f7472616e73666572546f6b656e733a207472616e7366657220616d6f756e7420657863656564732062616c616e636564434c4d383a3a5f7472616e73666572546f6b656e733a207472616e7366657220616d6f756e74206f766572666c6f777364434c4d383a3a616464546f546f74616c537570706c793a20616d6f756e74206f766572666c6f777364434c4d383a3a616464546f546f74616c537570706c793a20616d6f756e742065786365656473203936206269747364434c4d383a3a7472616e736665723a20616d6f756e742065786365656473203936206269747364434c4d383a3a7472616e7366657246726f6d3a207472616e7366657220616d6f756e742065786365656473207370656e64657220616c6c6f77616e636564434c4d383a3a617070726f76653a20616d6f756e742065786365656473203936206269747364434c4d383a3a5f6d6f7665566f7465733a20766f746520616d6f756e7420756e646572666c6f777364434c4d383a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d62657220657863656564732033322062697473a2646970667358221220034b11cf7e6ec37588cc77eb13b439f11d636e9d7a79e87e033390dd0f277c2164736f6c63430008030033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "params": { + "account": "The address of the account holding the funds", + "spender": "The address of the account spending the funds" + }, + "returns": { + "_0": "The number of tokens approved" + } + }, + "approve(address,uint256)": { + "details": "This will overwrite the approval amount for `spender` and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)", + "params": { + "rawAmount": "The number of tokens that are approved (2^256-1 means infinite)", + "spender": "The address of the account which may transfer tokens" + }, + "returns": { + "_0": "Whether or not the approval succeeded" + } + }, + "balanceOf(address)": { + "params": { + "account": "The address of the account to get the balance of" + }, + "returns": { + "_0": "The number of tokens held" + } + }, + "constructor": { + "params": { + "account": "The initial account to grant all the tokens" + } + }, + "delegate(address)": { + "params": { + "delegatee": "The address to delegate votes to" + } + }, + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": { + "params": { + "delegatee": "The address to delegate votes to", + "expiry": "The time at which to expire the signature", + "nonce": "The contract state required to match the signature", + "r": "Half of the ECDSA signature pair", + "s": "Half of the ECDSA signature pair", + "v": "The recovery byte of the signature" + } + }, + "getCurrentVotes(address)": { + "params": { + "account": "The address to get votes balance" + }, + "returns": { + "_0": "The number of current votes for `account`" + } + }, + "getPriorVotes(address,uint256)": { + "details": "Block number must be a finalized block or else this function will revert to prevent misinformation.", + "params": { + "account": "The address of the account to check", + "blockNumber": "The block number to get the vote balance at" + }, + "returns": { + "_0": "The number of votes the account had as of the given block" + } + }, + "transfer(address,uint256)": { + "params": { + "dst": "The address of the destination account", + "rawAmount": "The number of tokens to transfer" + }, + "returns": { + "_0": "Whether or not the transfer succeeded" + } + }, + "transferFrom(address,address,uint256)": { + "params": { + "dst": "The address of the destination account", + "rawAmount": "The number of tokens to transfer", + "src": "The address of the source account" + }, + "returns": { + "_0": "Whether or not the transfer succeeded" + } + } + }, + "stateVariables": { + "allowances": { + "details": "Allowance amounts on behalf of others" + }, + "balances": { + "details": "Official record of token balances for each account" + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "Approval(address,address,uint256)": { + "notice": "The standard EIP-20 approval event" + }, + "DelegateChanged(address,address,address)": { + "notice": "An event thats emitted when an account changes its delegate" + }, + "DelegateVotesChanged(address,uint256,uint256)": { + "notice": "An event thats emitted when a delegate account's vote balance changes" + }, + "Transfer(address,address,uint256)": { + "notice": "The standard EIP-20 transfer event" + } + }, + "kind": "user", + "methods": { + "DELEGATION_TYPEHASH()": { + "notice": "The EIP-712 typehash for the delegation struct used by the contract" + }, + "DOMAIN_TYPEHASH()": { + "notice": "The EIP-712 typehash for the contract's domain" + }, + "allowance(address,address)": { + "notice": "Get the number of tokens `spender` is approved to spend on behalf of `account`" + }, + "approve(address,uint256)": { + "notice": "Approve `spender` to transfer up to `amount` from `src`" + }, + "balanceOf(address)": { + "notice": "Get the number of tokens held by the `account`" + }, + "checkpoints(address,uint32)": { + "notice": "A record of votes checkpoints for each account, by index" + }, + "constructor": { + "notice": "Construct a new dCLM8 token" + }, + "decimals()": { + "notice": "EIP-20 token decimals for this token" + }, + "delegate(address)": { + "notice": "Delegate votes from `msg.sender` to `delegatee`" + }, + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": { + "notice": "Delegates votes from signatory to `delegatee`" + }, + "delegates(address)": { + "notice": "A record of each accounts delegate" + }, + "getCurrentVotes(address)": { + "notice": "Gets the current votes balance for `account`" + }, + "getPriorVotes(address,uint256)": { + "notice": "Determine the prior number of votes for an account as of a block number" + }, + "governor()": { + "notice": "Governor to be set after deploy for permissions to burn tokens (only set once)" + }, + "initialHolder()": { + "notice": "Initial holder of all DAO tokens" + }, + "name()": { + "notice": "EIP-20 token name for this token" + }, + "nonces(address)": { + "notice": "A record of states for signing / validating signatures" + }, + "numCheckpoints(address)": { + "notice": "The number of checkpoints for each account" + }, + "symbol()": { + "notice": "EIP-20 token symbol for this token" + }, + "totalSupply()": { + "notice": "Total number of tokens in circulation" + }, + "transfer(address,uint256)": { + "notice": "Transfer `amount` tokens from `msg.sender` to `dst`" + }, + "transferFrom(address,address,uint256)": { + "notice": "Transfer `amount` tokens from `src` to `dst`" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 18, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "totalSupply", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 21, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "initialHolder", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 28, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "governor", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 35, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "allowances", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint96))" + }, + { + "astId": 40, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "balances", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_address,t_uint96)" + }, + { + "astId": 45, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "delegates", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 58, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "checkpoints", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)50_storage))" + }, + { + "astId": 63, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "numCheckpoints", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_uint32)" + }, + { + "astId": 80, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "nonces", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint96))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint96))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint96)" + }, + "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)50_storage))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint32 => struct DAOToken.Checkpoint))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint32,t_struct(Checkpoint)50_storage)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_address,t_uint32)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint32)", + "numberOfBytes": "32", + "value": "t_uint32" + }, + "t_mapping(t_address,t_uint96)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint96)", + "numberOfBytes": "32", + "value": "t_uint96" + }, + "t_mapping(t_uint32,t_struct(Checkpoint)50_storage)": { + "encoding": "mapping", + "key": "t_uint32", + "label": "mapping(uint32 => struct DAOToken.Checkpoint)", + "numberOfBytes": "32", + "value": "t_struct(Checkpoint)50_storage" + }, + "t_struct(Checkpoint)50_storage": { + "encoding": "inplace", + "label": "struct DAOToken.Checkpoint", + "members": [ + { + "astId": 47, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "fromBlock", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 49, + "contract": "solidity/Governance/DAOToken.sol:DAOToken", + "label": "votes", + "offset": 4, + "slot": "0", + "type": "t_uint96" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint96": { + "encoding": "inplace", + "label": "uint96", + "numberOfBytes": "12" + } + } + } +} \ No newline at end of file diff --git a/hardhat/deployments/hedera-testnet/Timelock.json b/hardhat/deployments/hedera-testnet/Timelock.json new file mode 100644 index 000000000..7e29be291 --- /dev/null +++ b/hardhat/deployments/hedera-testnet/Timelock.json @@ -0,0 +1,538 @@ +{ + "address": "0x417dd5d7f79396519C4c85Dd3C0556cb07C0dc1D", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "delay_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "CancelTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "ExecuteTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "newDelay", + "type": "uint256" + } + ], + "name": "NewDelay", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "QueueTransaction", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "GRACE_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAXIMUM_DELAY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINIMUM_DELAY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "cancelTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "delay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "executeTransaction", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", + "type": "uint256" + } + ], + "name": "queueTransaction", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "queuedTransactions", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "delay_", + "type": "uint256" + } + ], + "name": "setDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pendingAdmin_", + "type": "address" + } + ], + "name": "setPendingAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xb2c4c52a2e38b5076540870cda76b83d5d0d749769fd6420f731156b24d139ac", + "receipt": { + "to": "0x00000000000000000000000000000000003Bd90d", + "from": "0x000000000000000000000000000000000037f97F", + "contractAddress": "0x417dd5d7f79396519C4c85Dd3C0556cb07C0dc1D", + "transactionIndex": 5, + "gasUsed": "320000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x361dee0bd4a82ce05e17c4b0bf58e868f843d26ca4326880aa870cc215734855", + "transactionHash": "0xb2c4c52a2e38b5076540870cda76b83d5d0d749769fd6420f731156b24d139ac", + "logs": [], + "blockNumber": 2541094, + "cumulativeGasUsed": "320000", + "status": 1, + "byzantium": true + }, + "args": [ + "0x82c12DF8ea6197A37Fc801F16E71b7b86A457d1C", + 172800 + ], + "numDeployments": 1, + "solcInputHash": "9cae68ccb2da1ec502699fbdf8934a04", + "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"delay_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"eta\",\"type\":\"uint256\"}],\"name\":\"CancelTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"eta\",\"type\":\"uint256\"}],\"name\":\"ExecuteTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"NewAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newDelay\",\"type\":\"uint256\"}],\"name\":\"NewDelay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPendingAdmin\",\"type\":\"address\"}],\"name\":\"NewPendingAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"eta\",\"type\":\"uint256\"}],\"name\":\"QueueTransaction\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"GRACE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAXIMUM_DELAY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_DELAY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"eta\",\"type\":\"uint256\"}],\"name\":\"cancelTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"delay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"eta\",\"type\":\"uint256\"}],\"name\":\"executeTransaction\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"eta\",\"type\":\"uint256\"}],\"name\":\"queueTransaction\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"queuedTransactions\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"delay_\",\"type\":\"uint256\"}],\"name\":\"setDelay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pendingAdmin_\",\"type\":\"address\"}],\"name\":\"setPendingAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Governance/Timelock.sol\":\"Timelock\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// CAUTION\\n// This version of SafeMath should only be used with Solidity 0.8 or later,\\n// because it relies on the compiler's built in overflow checks.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations.\\n *\\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\\n * now has built in overflow checking.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator.\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0f633a0223d9a1dcccfcf38a64c9de0874dfcbfac0c6941ccf074d63a2ce0e1e\",\"license\":\"MIT\"},\"solidity/Governance/Timelock.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n// SPDX-License-Identifier: BSD-3-Clause\\n\\n/* Copyright 2021 Compound Labs, Inc.\\nRedistribution and use in source and binary forms, with or without\\nmodification, are permitted provided that the following conditions are met:\\n1. Redistributions of source code must retain the above copyright notice, this\\nlist of conditions and the following disclaimer.\\n2. Redistributions in binary form must reproduce the above copyright notice,\\nthis list of conditions and the following disclaimer in the documentation\\nand/or other materials provided with the distribution.\\n3. Neither the name of the copyright holder nor the names of its contributors\\nmay be used to endorse or promote products derived from this software without\\nspecific prior written permission.\\n\\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \\\"AS IS\\\" AND\\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */\\n\\n// Original work from Compound: https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol\\n// Modified to work in the NetEmissionsTokenNetwork system\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\ncontract Timelock {\\n using SafeMath for uint256;\\n\\n event NewAdmin(address indexed newAdmin);\\n event NewPendingAdmin(address indexed newPendingAdmin);\\n event NewDelay(uint256 indexed newDelay);\\n event CancelTransaction(\\n bytes32 indexed txHash,\\n address indexed target,\\n uint256 value,\\n string signature,\\n bytes data,\\n uint256 eta\\n );\\n event ExecuteTransaction(\\n bytes32 indexed txHash,\\n address indexed target,\\n uint256 value,\\n string signature,\\n bytes data,\\n uint256 eta\\n );\\n event QueueTransaction(\\n bytes32 indexed txHash,\\n address indexed target,\\n uint256 value,\\n string signature,\\n bytes data,\\n uint256 eta\\n );\\n\\n uint256 public constant GRACE_PERIOD = 14 days;\\n uint256 public constant MINIMUM_DELAY = 2 days;\\n uint256 public constant MAXIMUM_DELAY = 30 days;\\n\\n address public admin;\\n address public pendingAdmin;\\n uint256 public delay;\\n\\n mapping(bytes32 => bool) public queuedTransactions;\\n\\n constructor(address admin_, uint256 delay_) {\\n require(\\n delay_ >= MINIMUM_DELAY,\\n \\\"Timelock::constructor: Delay must exceed minimum delay.\\\"\\n );\\n require(\\n delay_ <= MAXIMUM_DELAY,\\n \\\"Timelock::setDelay: Delay must not exceed maximum delay.\\\"\\n );\\n\\n admin = admin_;\\n delay = delay_;\\n }\\n\\n fallback() external payable {}\\n\\n receive() external payable {}\\n\\n function setDelay(uint256 delay_) public {\\n require(\\n msg.sender == address(this),\\n \\\"Timelock::setDelay: Call must come from Timelock.\\\"\\n );\\n require(\\n delay_ >= MINIMUM_DELAY,\\n \\\"Timelock::setDelay: Delay must exceed minimum delay.\\\"\\n );\\n require(\\n delay_ <= MAXIMUM_DELAY,\\n \\\"Timelock::setDelay: Delay must not exceed maximum delay.\\\"\\n );\\n delay = delay_;\\n\\n emit NewDelay(delay);\\n }\\n\\n function acceptAdmin() public {\\n require(\\n msg.sender == pendingAdmin,\\n \\\"Timelock::acceptAdmin: Call must come from pendingAdmin.\\\"\\n );\\n admin = msg.sender;\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(admin);\\n }\\n\\n function setPendingAdmin(address pendingAdmin_) public {\\n require(\\n msg.sender == address(this),\\n \\\"Timelock::setPendingAdmin: Call must come from Timelock.\\\"\\n );\\n pendingAdmin = pendingAdmin_;\\n\\n emit NewPendingAdmin(pendingAdmin);\\n }\\n\\n function queueTransaction(\\n address target,\\n uint256 value,\\n string memory signature,\\n bytes memory data,\\n uint256 eta\\n ) public returns (bytes32) {\\n require(\\n msg.sender == admin,\\n \\\"Timelock::queueTransaction: Call must come from admin.\\\"\\n );\\n require(\\n eta >= getBlockTimestamp().add(delay),\\n \\\"Timelock::queueTransaction: Estimated execution block must satisfy delay.\\\"\\n );\\n\\n bytes32 txHash = keccak256(\\n abi.encode(target, value, signature, data, eta)\\n );\\n queuedTransactions[txHash] = true;\\n\\n emit QueueTransaction(txHash, target, value, signature, data, eta);\\n return txHash;\\n }\\n\\n function cancelTransaction(\\n address target,\\n uint256 value,\\n string memory signature,\\n bytes memory data,\\n uint256 eta\\n ) public {\\n require(\\n msg.sender == admin,\\n \\\"Timelock::cancelTransaction: Call must come from admin.\\\"\\n );\\n\\n bytes32 txHash = keccak256(\\n abi.encode(target, value, signature, data, eta)\\n );\\n queuedTransactions[txHash] = false;\\n\\n emit CancelTransaction(txHash, target, value, signature, data, eta);\\n }\\n\\n function executeTransaction(\\n address target,\\n uint256 value,\\n string memory signature,\\n bytes memory data,\\n uint256 eta\\n ) public payable returns (bytes memory) {\\n require(\\n msg.sender == admin,\\n \\\"Timelock::executeTransaction: Call must come from admin.\\\"\\n );\\n\\n bytes32 txHash = keccak256(\\n abi.encode(target, value, signature, data, eta)\\n );\\n require(\\n queuedTransactions[txHash],\\n \\\"Timelock::executeTransaction: Transaction hasn't been queued.\\\"\\n );\\n require(\\n getBlockTimestamp() >= eta,\\n \\\"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\\\"\\n );\\n require(\\n getBlockTimestamp() <= eta.add(GRACE_PERIOD),\\n \\\"Timelock::executeTransaction: Transaction is stale.\\\"\\n );\\n\\n queuedTransactions[txHash] = false;\\n\\n bytes memory callData;\\n\\n if (bytes(signature).length == 0) {\\n callData = data;\\n } else {\\n callData = abi.encodePacked(\\n bytes4(keccak256(bytes(signature))),\\n data\\n );\\n }\\n\\n (bool success, bytes memory returnData) = target.call{value: value}(\\n callData\\n );\\n require(\\n success,\\n \\\"Timelock::executeTransaction: Transaction execution reverted.\\\"\\n );\\n\\n emit ExecuteTransaction(txHash, target, value, signature, data, eta);\\n\\n return returnData;\\n }\\n\\n function getBlockTimestamp() internal view returns (uint256) {\\n // solium-disable-next-line security/no-block-members\\n return block.timestamp;\\n }\\n}\\n\",\"keccak256\":\"0x8aa7dd423825f798d7557ef41ce067e685e694910345b10d3846154bf306946d\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506040516110c73803806110c783398101604081905261002f9161014f565b6202a3008110156100ad5760405162461bcd60e51b815260206004820152603760248201527f54696d656c6f636b3a3a636f6e7374727563746f723a2044656c6179206d757360448201527f7420657863656564206d696e696d756d2064656c61792e00000000000000000060648201526084015b60405180910390fd5b62278d008111156101265760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60448201527f6f7420657863656564206d6178696d756d2064656c61792e000000000000000060648201526084016100a4565b600080546001600160a01b0319166001600160a01b039390931692909217909155600255610187565b60008060408385031215610161578182fd5b82516001600160a01b0381168114610177578283fd5b6020939093015192949293505050565b610f31806101966000396000f3fe6080604052600436106100c65760003560e01c80636a42b8f81161007f578063c1a287e211610059578063c1a287e2146101f7578063e177246e1461020e578063f2b065371461022e578063f851a4401461026e576100cd565b80636a42b8f8146101b35780637d645fab146101c9578063b1b43ae5146101e0576100cd565b80630825f38f146100cf5780630e18b681146100f8578063267822471461010d5780633a66f901146101455780634dd18bf514610173578063591fcdfe14610193576100cd565b366100cd57005b005b6100e26100dd366004610c98565b61028e565b6040516100ef9190610e21565b60405180910390f35b34801561010457600080fd5b506100cd6105ff565b34801561011957600080fd5b5060015461012d906001600160a01b031681565b6040516001600160a01b0390911681526020016100ef565b34801561015157600080fd5b50610165610160366004610c98565b6106c8565b6040519081526020016100ef565b34801561017f57600080fd5b506100cd61018e366004610c7e565b61087b565b34801561019f57600080fd5b506100cd6101ae366004610c98565b61093a565b3480156101bf57600080fd5b5061016560025481565b3480156101d557600080fd5b5061016562278d0081565b3480156101ec57600080fd5b506101656202a30081565b34801561020357600080fd5b506101656212750081565b34801561021a57600080fd5b506100cd610229366004610d44565b610a54565b34801561023a57600080fd5b5061025e610249366004610d44565b60036020526000908152604090205460ff1681565b60405190151581526020016100ef565b34801561027a57600080fd5b5060005461012d906001600160a01b031681565b6000546060906001600160a01b031633146103165760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20436160448201527f6c6c206d75737420636f6d652066726f6d2061646d696e2e000000000000000060648201526084015b60405180910390fd5b60008686868686604051602001610331959493929190610dd5565b60408051601f1981840301815291815281516020928301206000818152600390935291205490915060ff166103bc5760405162461bcd60e51b815260206004820152603d6024820152600080516020610edc83398151915260448201527f616e73616374696f6e206861736e2774206265656e207175657565642e000000606482015260840161030d565b8242101561042e5760405162461bcd60e51b81526020600482015260456024820152600080516020610edc83398151915260448201527f616e73616374696f6e206861736e2774207375727061737365642074696d65206064820152643637b1b59760d91b608482015260a40161030d565b61043b8362127500610bd9565b4211156104945760405162461bcd60e51b81526020600482015260336024820152600080516020610edc83398151915260448201527230b739b0b1ba34b7b71034b99039ba30b6329760691b606482015260840161030d565b6000818152600360205260409020805460ff1916905584516060906104ba5750836104e6565b8580519060200120856040516020016104d4929190610d88565b60405160208183030381529060405290505b600080896001600160a01b031689846040516105029190610db9565b60006040518083038185875af1925050503d806000811461053f576040519150601f19603f3d011682016040523d82523d6000602084013e610544565b606091505b5091509150816105aa5760405162461bcd60e51b815260206004820152603d6024820152600080516020610edc83398151915260448201527f616e73616374696f6e20657865637574696f6e2072657665727465642e000000606482015260840161030d565b896001600160a01b0316847fa560e3198060a2f10670c1ec5b403077ea6ae93ca8de1c32b451dc1a943cd6e78b8b8b8b6040516105ea9493929190610e34565b60405180910390a39998505050505050505050565b6001546001600160a01b0316331461067f5760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a61636365707441646d696e3a2043616c6c206d75737460448201527f20636f6d652066726f6d2070656e64696e6741646d696e2e0000000000000000606482015260840161030d565b60008054336001600160a01b0319918216811783556001805490921690915560405190917f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c91a2565b600080546001600160a01b031633146107425760405162461bcd60e51b815260206004820152603660248201527f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a2043616c6c6044820152751036bab9ba1031b7b6b290333937b69030b236b4b71760511b606482015260840161030d565b61075560025461074f4290565b90610bd9565b8210156107dc5760405162461bcd60e51b815260206004820152604960248201527f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a204573746960448201527f6d6174656420657865637574696f6e20626c6f636b206d757374207361746973606482015268333c903232b630bc9760b91b608482015260a40161030d565b600086868686866040516020016107f7959493929190610dd5565b60408051601f19818403018152828252805160209182012060008181526003909252919020805460ff1916600117905591506001600160a01b0388169082907f76e2796dc3a81d57b0e8504b647febcbeeb5f4af818e164f11eef8131a6a763f90610869908a908a908a908a90610e34565b60405180910390a39695505050505050565b3330146108f05760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a73657450656e64696e6741646d696e3a2043616c6c2060448201527f6d75737420636f6d652066726f6d2054696d656c6f636b2e0000000000000000606482015260840161030d565b600180546001600160a01b0319166001600160a01b0383169081179091556040517f69d78e38a01985fbb1462961809b4b2d65531bc93b2b94037f3334b82ca4a75690600090a250565b6000546001600160a01b031633146109ba5760405162461bcd60e51b815260206004820152603760248201527f54696d656c6f636b3a3a63616e63656c5472616e73616374696f6e3a2043616c60448201527f6c206d75737420636f6d652066726f6d2061646d696e2e000000000000000000606482015260840161030d565b600085858585856040516020016109d5959493929190610dd5565b60408051601f19818403018152828252805160209182012060008181526003909252919020805460ff1916905591506001600160a01b0387169082907f2fffc091a501fd91bfbff27141450d3acb40fb8e6d8382b243ec7a812a3aaf8790610a44908990899089908990610e34565b60405180910390a3505050505050565b333014610abd5760405162461bcd60e51b815260206004820152603160248201527f54696d656c6f636b3a3a73657444656c61793a2043616c6c206d75737420636f60448201527036b290333937b6902a34b6b2b637b1b59760791b606482015260840161030d565b6202a300811015610b2d5760405162461bcd60e51b815260206004820152603460248201527f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d75737420656044820152733c31b2b2b21036b4b734b6bab6903232b630bc9760611b606482015260840161030d565b62278d00811115610ba65760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60448201527f6f7420657863656564206d6178696d756d2064656c61792e0000000000000000606482015260840161030d565b600281905560405181907f948b1f6a42ee138b7e34058ba85a37f716d55ff25ff05a763f15bed6a04c8d2c90600090a250565b6000610be58284610e71565b9392505050565b600067ffffffffffffffff80841115610c0757610c07610ec5565b604051601f8501601f19908116603f01168101908282118183101715610c2f57610c2f610ec5565b81604052809350858152868686011115610c4857600080fd5b858560208301376000602087830101525050509392505050565b80356001600160a01b0381168114610c7957600080fd5b919050565b600060208284031215610c8f578081fd5b610be582610c62565b600080600080600060a08688031215610caf578081fd5b610cb886610c62565b945060208601359350604086013567ffffffffffffffff80821115610cdb578283fd5b818801915088601f830112610cee578283fd5b610cfd89833560208501610bec565b94506060880135915080821115610d12578283fd5b508601601f81018813610d23578182fd5b610d3288823560208401610bec565b95989497509295608001359392505050565b600060208284031215610d55578081fd5b5035919050565b60008151808452610d74816020860160208601610e95565b601f01601f19169290920160200192915050565b6001600160e01b0319831681528151600090610dab816004850160208701610e95565b919091016004019392505050565b60008251610dcb818460208701610e95565b9190910192915050565b600060018060a01b038716825285602083015260a06040830152610dfc60a0830186610d5c565b8281036060840152610e0e8186610d5c565b9150508260808301529695505050505050565b600060208252610be56020830184610d5c565b600085825260806020830152610e4d6080830186610d5c565b8281036040840152610e5f8186610d5c565b91505082606083015295945050505050565b60008219821115610e9057634e487b7160e01b81526011600452602481fd5b500190565b60005b83811015610eb0578181015183820152602001610e98565b83811115610ebf576000848401525b50505050565b634e487b7160e01b600052604160045260246000fdfe54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a205472a264697066735822122023a2fbc20f21df69cf1a891071c62c839d98c2f14d7155eef94905053582cb6e64736f6c63430008030033", + "deployedBytecode": "0x6080604052600436106100c65760003560e01c80636a42b8f81161007f578063c1a287e211610059578063c1a287e2146101f7578063e177246e1461020e578063f2b065371461022e578063f851a4401461026e576100cd565b80636a42b8f8146101b35780637d645fab146101c9578063b1b43ae5146101e0576100cd565b80630825f38f146100cf5780630e18b681146100f8578063267822471461010d5780633a66f901146101455780634dd18bf514610173578063591fcdfe14610193576100cd565b366100cd57005b005b6100e26100dd366004610c98565b61028e565b6040516100ef9190610e21565b60405180910390f35b34801561010457600080fd5b506100cd6105ff565b34801561011957600080fd5b5060015461012d906001600160a01b031681565b6040516001600160a01b0390911681526020016100ef565b34801561015157600080fd5b50610165610160366004610c98565b6106c8565b6040519081526020016100ef565b34801561017f57600080fd5b506100cd61018e366004610c7e565b61087b565b34801561019f57600080fd5b506100cd6101ae366004610c98565b61093a565b3480156101bf57600080fd5b5061016560025481565b3480156101d557600080fd5b5061016562278d0081565b3480156101ec57600080fd5b506101656202a30081565b34801561020357600080fd5b506101656212750081565b34801561021a57600080fd5b506100cd610229366004610d44565b610a54565b34801561023a57600080fd5b5061025e610249366004610d44565b60036020526000908152604090205460ff1681565b60405190151581526020016100ef565b34801561027a57600080fd5b5060005461012d906001600160a01b031681565b6000546060906001600160a01b031633146103165760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20436160448201527f6c6c206d75737420636f6d652066726f6d2061646d696e2e000000000000000060648201526084015b60405180910390fd5b60008686868686604051602001610331959493929190610dd5565b60408051601f1981840301815291815281516020928301206000818152600390935291205490915060ff166103bc5760405162461bcd60e51b815260206004820152603d6024820152600080516020610edc83398151915260448201527f616e73616374696f6e206861736e2774206265656e207175657565642e000000606482015260840161030d565b8242101561042e5760405162461bcd60e51b81526020600482015260456024820152600080516020610edc83398151915260448201527f616e73616374696f6e206861736e2774207375727061737365642074696d65206064820152643637b1b59760d91b608482015260a40161030d565b61043b8362127500610bd9565b4211156104945760405162461bcd60e51b81526020600482015260336024820152600080516020610edc83398151915260448201527230b739b0b1ba34b7b71034b99039ba30b6329760691b606482015260840161030d565b6000818152600360205260409020805460ff1916905584516060906104ba5750836104e6565b8580519060200120856040516020016104d4929190610d88565b60405160208183030381529060405290505b600080896001600160a01b031689846040516105029190610db9565b60006040518083038185875af1925050503d806000811461053f576040519150601f19603f3d011682016040523d82523d6000602084013e610544565b606091505b5091509150816105aa5760405162461bcd60e51b815260206004820152603d6024820152600080516020610edc83398151915260448201527f616e73616374696f6e20657865637574696f6e2072657665727465642e000000606482015260840161030d565b896001600160a01b0316847fa560e3198060a2f10670c1ec5b403077ea6ae93ca8de1c32b451dc1a943cd6e78b8b8b8b6040516105ea9493929190610e34565b60405180910390a39998505050505050505050565b6001546001600160a01b0316331461067f5760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a61636365707441646d696e3a2043616c6c206d75737460448201527f20636f6d652066726f6d2070656e64696e6741646d696e2e0000000000000000606482015260840161030d565b60008054336001600160a01b0319918216811783556001805490921690915560405190917f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c91a2565b600080546001600160a01b031633146107425760405162461bcd60e51b815260206004820152603660248201527f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a2043616c6c6044820152751036bab9ba1031b7b6b290333937b69030b236b4b71760511b606482015260840161030d565b61075560025461074f4290565b90610bd9565b8210156107dc5760405162461bcd60e51b815260206004820152604960248201527f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a204573746960448201527f6d6174656420657865637574696f6e20626c6f636b206d757374207361746973606482015268333c903232b630bc9760b91b608482015260a40161030d565b600086868686866040516020016107f7959493929190610dd5565b60408051601f19818403018152828252805160209182012060008181526003909252919020805460ff1916600117905591506001600160a01b0388169082907f76e2796dc3a81d57b0e8504b647febcbeeb5f4af818e164f11eef8131a6a763f90610869908a908a908a908a90610e34565b60405180910390a39695505050505050565b3330146108f05760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a73657450656e64696e6741646d696e3a2043616c6c2060448201527f6d75737420636f6d652066726f6d2054696d656c6f636b2e0000000000000000606482015260840161030d565b600180546001600160a01b0319166001600160a01b0383169081179091556040517f69d78e38a01985fbb1462961809b4b2d65531bc93b2b94037f3334b82ca4a75690600090a250565b6000546001600160a01b031633146109ba5760405162461bcd60e51b815260206004820152603760248201527f54696d656c6f636b3a3a63616e63656c5472616e73616374696f6e3a2043616c60448201527f6c206d75737420636f6d652066726f6d2061646d696e2e000000000000000000606482015260840161030d565b600085858585856040516020016109d5959493929190610dd5565b60408051601f19818403018152828252805160209182012060008181526003909252919020805460ff1916905591506001600160a01b0387169082907f2fffc091a501fd91bfbff27141450d3acb40fb8e6d8382b243ec7a812a3aaf8790610a44908990899089908990610e34565b60405180910390a3505050505050565b333014610abd5760405162461bcd60e51b815260206004820152603160248201527f54696d656c6f636b3a3a73657444656c61793a2043616c6c206d75737420636f60448201527036b290333937b6902a34b6b2b637b1b59760791b606482015260840161030d565b6202a300811015610b2d5760405162461bcd60e51b815260206004820152603460248201527f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d75737420656044820152733c31b2b2b21036b4b734b6bab6903232b630bc9760611b606482015260840161030d565b62278d00811115610ba65760405162461bcd60e51b815260206004820152603860248201527f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60448201527f6f7420657863656564206d6178696d756d2064656c61792e0000000000000000606482015260840161030d565b600281905560405181907f948b1f6a42ee138b7e34058ba85a37f716d55ff25ff05a763f15bed6a04c8d2c90600090a250565b6000610be58284610e71565b9392505050565b600067ffffffffffffffff80841115610c0757610c07610ec5565b604051601f8501601f19908116603f01168101908282118183101715610c2f57610c2f610ec5565b81604052809350858152868686011115610c4857600080fd5b858560208301376000602087830101525050509392505050565b80356001600160a01b0381168114610c7957600080fd5b919050565b600060208284031215610c8f578081fd5b610be582610c62565b600080600080600060a08688031215610caf578081fd5b610cb886610c62565b945060208601359350604086013567ffffffffffffffff80821115610cdb578283fd5b818801915088601f830112610cee578283fd5b610cfd89833560208501610bec565b94506060880135915080821115610d12578283fd5b508601601f81018813610d23578182fd5b610d3288823560208401610bec565b95989497509295608001359392505050565b600060208284031215610d55578081fd5b5035919050565b60008151808452610d74816020860160208601610e95565b601f01601f19169290920160200192915050565b6001600160e01b0319831681528151600090610dab816004850160208701610e95565b919091016004019392505050565b60008251610dcb818460208701610e95565b9190910192915050565b600060018060a01b038716825285602083015260a06040830152610dfc60a0830186610d5c565b8281036060840152610e0e8186610d5c565b9150508260808301529695505050505050565b600060208252610be56020830184610d5c565b600085825260806020830152610e4d6080830186610d5c565b8281036040840152610e5f8186610d5c565b91505082606083015295945050505050565b60008219821115610e9057634e487b7160e01b81526011600452602481fd5b500190565b60005b83811015610eb0578181015183820152602001610e98565b83811115610ebf576000848401525b50505050565b634e487b7160e01b600052604160045260246000fdfe54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a205472a264697066735822122023a2fbc20f21df69cf1a891071c62c839d98c2f14d7155eef94905053582cb6e64736f6c63430008030033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 5648, + "contract": "solidity/Governance/Timelock.sol:Timelock", + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 5650, + "contract": "solidity/Governance/Timelock.sol:Timelock", + "label": "pendingAdmin", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 5652, + "contract": "solidity/Governance/Timelock.sol:Timelock", + "label": "delay", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 5656, + "contract": "solidity/Governance/Timelock.sol:Timelock", + "label": "queuedTransactions", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_bytes32,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_bool)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/hardhat/deployments/hedera-testnet/solcInputs/303f0d0861904a4ebaa538b95b45b55f.json b/hardhat/deployments/hedera-testnet/solcInputs/303f0d0861904a4ebaa538b95b45b55f.json new file mode 100644 index 000000000..4e29e9169 --- /dev/null +++ b/hardhat/deployments/hedera-testnet/solcInputs/303f0d0861904a4ebaa538b95b45b55f.json @@ -0,0 +1,35 @@ +{ + "language": "Solidity", + "sources": { + "solidity/Governance/DAOToken.sol": { + "content": "pragma solidity ^0.8.0;\npragma experimental ABIEncoderV2;\n\n// SPDX-License-Identifier: BSD-3-Clause\n\n/* Copyright 2021 Compound Labs, Inc.\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n3. Neither the name of the copyright holder nor the names of its contributors\nmay be used to endorse or promote products derived from this software without\nspecific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */\n\n// Original work from Compound: https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol\n// Modified to work in the NetEmissionsTokenNetwork system\n\ncontract DAOToken {\n /// @notice EIP-20 token name for this token\n string public constant name = \"Climate DAO Token\";\n\n /// @notice EIP-20 token symbol for this token\n string public constant symbol = \"dCLM8\";\n\n /// @notice EIP-20 token decimals for this token\n uint8 public constant decimals = 18;\n\n /// @notice Total number of tokens in circulation\n uint256 public totalSupply = 10000000e18; // 10 million dCLM8\n\n /// @notice Initial holder of all DAO tokens\n address public initialHolder;\n\n /// @notice Governor to be set after deploy for permissions to burn tokens (only set once)\n address public governor = address(0);\n\n /// @dev Allowance amounts on behalf of others\n mapping(address => mapping(address => uint96)) internal allowances;\n\n /// @dev Official record of token balances for each account\n mapping(address => uint96) internal balances;\n\n /// @notice A record of each accounts delegate\n mapping(address => address) public delegates;\n\n /// @notice A checkpoint for marking number of votes from a given block\n struct Checkpoint {\n uint32 fromBlock;\n uint96 votes;\n }\n\n /// @notice A record of votes checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH =\n keccak256(\n \"EIP712Domain(string name,uint256 chainId,address verifyingContract)\"\n );\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint256) public nonces;\n\n /// @notice An event thats emitted when an account changes its delegate\n event DelegateChanged(\n address indexed delegator,\n address indexed fromDelegate,\n address indexed toDelegate\n );\n\n /// @notice An event thats emitted when a delegate account's vote balance changes\n event DelegateVotesChanged(\n address indexed delegate,\n uint256 previousBalance,\n uint256 newBalance\n );\n\n /// @notice The standard EIP-20 transfer event\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @notice The standard EIP-20 approval event\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 amount\n );\n\n /**\n * @notice Construct a new dCLM8 token\n * @param account The initial account to grant all the tokens\n */\n constructor(address account) {\n balances[account] = uint96(totalSupply);\n initialHolder = account;\n emit Transfer(address(0), account, totalSupply);\n }\n\n /**\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\n * @param account The address of the account holding the funds\n * @param spender The address of the account spending the funds\n * @return The number of tokens approved\n */\n function allowance(address account, address spender)\n external\n view\n returns (uint256)\n {\n return allowances[account][spender];\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint256 rawAmount)\n external\n returns (bool)\n {\n uint96 amount;\n if (rawAmount == type(uint256).max) {\n amount = type(uint96).max;\n } else {\n amount = safe96(\n rawAmount,\n \"dCLM8::approve: amount exceeds 96 bits\"\n );\n }\n\n allowances[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n /**\n * @notice Get the number of tokens held by the `account`\n * @param account The address of the account to get the balance of\n * @return The number of tokens held\n */\n function balanceOf(address account) external view returns (uint256) {\n return balances[account];\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint256 rawAmount) external returns (bool) {\n if ((msg.sender != initialHolder) && (msg.sender != governor)) {\n revert(\n \"dCLM8::transfer: sender must be initial holder or DAO governor\"\n );\n }\n\n uint96 amount = safe96(\n rawAmount,\n \"dCLM8::transfer: amount exceeds 96 bits\"\n );\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(\n address src,\n address dst,\n uint256 rawAmount\n ) external returns (bool) {\n if ((src != initialHolder) && (src != governor)) {\n revert(\n \"dCLM8::transfer: sender must be initial holder or DAO governor\"\n );\n }\n\n address spender = msg.sender;\n uint96 spenderAllowance = allowances[src][spender];\n uint96 amount = safe96(\n rawAmount,\n \"dCLM8::approve: amount exceeds 96 bits\"\n );\n\n if (spender != src && spenderAllowance != type(uint96).max) {\n uint96 newAllowance = sub96(\n spenderAllowance,\n amount,\n \"dCLM8::transferFrom: transfer amount exceeds spender allowance\"\n );\n allowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public {\n return _delegate(msg.sender, delegatee);\n }\n\n /**\n * @notice Delegates votes from signatory to `delegatee`\n * @param delegatee The address to delegate votes to\n * @param nonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v The recovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n bytes32 domainSeparator = keccak256(\n abi.encode(\n DOMAIN_TYPEHASH,\n keccak256(bytes(name)),\n getChainId(),\n address(this)\n )\n );\n bytes32 structHash = keccak256(\n abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)\n );\n bytes32 digest = keccak256(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n address signatory = ecrecover(digest, v, r, s);\n require(\n signatory != address(0),\n \"dCLM8::delegateBySig: invalid signature\"\n );\n require(\n nonce == nonces[signatory]++,\n \"dCLM8::delegateBySig: invalid nonce\"\n );\n require(\n block.timestamp <= expiry,\n \"dCLM8::delegateBySig: signature expired\"\n );\n return _delegate(signatory, delegatee);\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getCurrentVotes(address account) external view returns (uint96) {\n uint32 nCheckpoints = numCheckpoints[account];\n return\n nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n }\n\n /**\n * @notice Determine the prior number of votes for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param blockNumber The block number to get the vote balance at\n * @return The number of votes the account had as of the given block\n */\n function getPriorVotes(address account, uint256 blockNumber)\n public\n view\n returns (uint96)\n {\n require(\n blockNumber < block.number,\n \"dCLM8::getPriorVotes: not yet determined\"\n );\n\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\n return checkpoints[account][nCheckpoints - 1].votes;\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].fromBlock > blockNumber) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.fromBlock == blockNumber) {\n return cp.votes;\n } else if (cp.fromBlock < blockNumber) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return checkpoints[account][lower].votes;\n }\n\n function _burn(address account, uint96 amount) external {\n require(\n account != address(0),\n \"dCLM8::_burn: burn from the zero address\"\n );\n require(msg.sender == governor, \"dCLM8::_burn: must be governor\");\n\n uint96 accountBalance = balances[account];\n require(\n accountBalance >= amount,\n \"dCLM8::_burn: burn amount exceeds balance\"\n );\n balances[account] = accountBalance - amount;\n totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n }\n\n function _delegate(address delegator, address delegatee) internal {\n address currentDelegate = delegates[delegator];\n uint96 delegatorBalance = balances[delegator];\n delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _transferTokens(\n address src,\n address dst,\n uint96 amount\n ) internal {\n require(\n src != address(0),\n \"dCLM8::_transferTokens: cannot transfer from the zero address\"\n );\n require(\n dst != address(0),\n \"dCLM8::_transferTokens: cannot transfer to the zero address\"\n );\n\n balances[src] = sub96(\n balances[src],\n amount,\n \"dCLM8::_transferTokens: transfer amount exceeds balance\"\n );\n balances[dst] = add96(\n balances[dst],\n amount,\n \"dCLM8::_transferTokens: transfer amount overflows\"\n );\n emit Transfer(src, dst, amount);\n\n // If dst address has no delgatees, automatically set to self. Otherwise, transfer to dst's delegates\n if (delegates[dst] == address(0)) {\n _delegate(dst, dst);\n } else {\n _moveDelegates(delegates[src], delegates[dst], amount);\n }\n }\n\n function _lockTokens(address src, uint96 amount) external {\n require(msg.sender == governor, \"dCLM8::lockTokens: must be governor\");\n\n balances[src] = sub96(\n balances[src],\n amount,\n \"dCLM8::_transferTokens: transfer amount exceeds balance\"\n );\n balances[governor] = add96(\n balances[governor],\n amount,\n \"dCLM8::_transferTokens: transfer amount overflows\"\n );\n\n emit Transfer(src, governor, amount);\n }\n\n function _moveDelegates(\n address srcRep,\n address dstRep,\n uint96 amount\n ) internal {\n if (srcRep != dstRep && amount > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint96 srcRepOld = srcRepNum > 0\n ? checkpoints[srcRep][srcRepNum - 1].votes\n : 0;\n uint96 srcRepNew = sub96(\n srcRepOld,\n amount,\n \"dCLM8::_moveVotes: vote amount underflows\"\n );\n _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint96 dstRepOld = dstRepNum > 0\n ? checkpoints[dstRep][dstRepNum - 1].votes\n : 0;\n uint96 dstRepNew = add96(\n dstRepOld,\n amount,\n \"dCLM8::_moveVotes: vote amount overflows\"\n );\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n }\n }\n }\n\n function _writeCheckpoint(\n address delegatee,\n uint32 nCheckpoints,\n uint96 oldVotes,\n uint96 newVotes\n ) internal {\n uint32 blockNumber = safe32(\n block.number,\n \"dCLM8::_writeCheckpoint: block number exceeds 32 bits\"\n );\n\n if (\n nCheckpoints > 0 &&\n checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber\n ) {\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n } else {\n checkpoints[delegatee][nCheckpoints] = Checkpoint(\n blockNumber,\n newVotes\n );\n numCheckpoints[delegatee] = nCheckpoints + 1;\n }\n\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n }\n\n function safe32(uint256 n, string memory errorMessage)\n internal\n pure\n returns (uint32)\n {\n require(n < 2**32, errorMessage);\n return uint32(n);\n }\n\n function safe96(uint256 n, string memory errorMessage)\n internal\n pure\n returns (uint96)\n {\n require(n < 2**96, errorMessage);\n return uint96(n);\n }\n\n function add96(\n uint96 a,\n uint96 b,\n string memory errorMessage\n ) internal pure returns (uint96) {\n uint96 c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub96(\n uint96 a,\n uint96 b,\n string memory errorMessage\n ) internal pure returns (uint96) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function getChainId() internal view returns (uint256) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n return chainId;\n }\n\n function addToTotalSupply(uint256 amount) public {\n if ((msg.sender != initialHolder) && (msg.sender != governor)) {\n revert(\n \"dCLM8::addToTotalSupply: must be initial holder or DAO governor\"\n );\n }\n uint96 _amount = safe96(\n amount,\n \"dCLM8::addToTotalSupply: amount exceeds 96 bits\"\n );\n balances[msg.sender] = add96(\n balances[msg.sender],\n _amount,\n \"dCLM8::addToTotalSupply: amount overflows\"\n );\n totalSupply += amount;\n // also need to sync the delegate checkpoint\n _moveDelegates(address(0), msg.sender, _amount);\n }\n\n function getTotalSupply() external view returns (uint256) {\n return totalSupply;\n }\n\n function getInitialHolder() external view returns (address) {\n return initialHolder;\n }\n\n function setGovernor(address newGovernor) public {\n require(\n msg.sender == initialHolder,\n \"dCLM8::setGovernor: must be initial holder\"\n );\n governor = newGovernor;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/hardhat/deployments/hedera-testnet/solcInputs/9cae68ccb2da1ec502699fbdf8934a04.json b/hardhat/deployments/hedera-testnet/solcInputs/9cae68ccb2da1ec502699fbdf8934a04.json new file mode 100644 index 000000000..dbdc5ca12 --- /dev/null +++ b/hardhat/deployments/hedera-testnet/solcInputs/9cae68ccb2da1ec502699fbdf8934a04.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "solidity/CarbonTracker.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\npragma experimental ABIEncoderV2;\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Receiver.sol\";\n//import \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"./NetEmissionsTokenNetwork.sol\";\nimport {TxVerifier} from \"./Libraries/TxVerifier.sol\";\nimport {ArrayModifier} from \"./Libraries/ArrayModifier.sol\";\nimport {Tracker} from \"./Libraries/TrackerStructs.sol\";\n\n/**\n\nCarbonTracker is a contract used to transfer embedded emissions of products in a supply chain. \nSee https://wiki.hyperledger.org/display/CASIG/2022-09-12+Peer+Programming+Call\nKey concepts are:\n - Product is something that has embedded emissions. \n Oil and natural gas, plastics, electricity, square feet of office, etc ... \n - CarbonTracker tokens reference Products and tokens from the NET network,\n These represent product specific emission certificates for industry \n - Products have various attribtutes\n - normalized amounts that assign a weighted distribution of the \n CarbonTracker emissions to each product. Could be normalize energy \n content, e.g., BOE (barrels of oil equivalent), if emissions are \n allocated propotional to energy content of products, or unitless.\n - Arrays of units and unit amounts used to store specific attributes. \n For example gallons for oil and cubic feet of natural gas. \n - Trackee is the registered entitity that the tracker is issued for. \n E.g., a natural gas utility.\n\nWorkflow of the token:\n - Auditors registered with NET issue CarbtonTracker tokens\n - track() to create, or trackUpdate() to update an existing, tracker\n - these functions assign NETs to the tracker\n - issueProduct() for auditors to assign unique product amounts to a tracker\n - issue() to mark a tracker as Audited \n - approve an industry emission certificate\n - allow its products to be transfered to other accounts\n - transferProducts() to another trackee, customer, auditor, ...\n - The entire audited CarbonTracker can also be transffered, \n e.g., to an emission certificate dealer, investor, ...\n - trackProduct() track a previously issued product to a new tracker ID.\n - This funciton enables tracking accross product supply chains \n - getTotalEmissions() - calculate the total emissions of the CarbonTracker \n -based on its emissions network tokens\n - create to create another tracker, for example by the customer for its product. For example, it could be plastics or office space.\n - transferProductToTracker - transfer some of the original product to the new tracker. For example, transfer cubic feet of natural gas to plastics or office space.\n This transfers the emissions through the supply chain from one product to another.\n\n**/\n\ncontract CarbonTracker is ERC1155, AccessControl, ERC1155Holder {\n using SafeMath for uint256;\n using Counters for Counters.Counter;\n\n using TxVerifier for bytes32;\n //using TxVerifier for bytes;\n using TxVerifier for address;\n //using TxVerifier for uint32;\n //using TxVerifier for uint256;\n using TxVerifier for bool;\n\n using ArrayModifier for uint256;\n using ArrayModifier for uint256[];\n using ArrayModifier for mapping(uint256 => uint256);\n\n address public netAddress;\n NetEmissionsTokenNetwork public net;\n\n /**\n * @dev Structure of all tokens issued in this contract\n * tokenId - Auto-increments whenever new tokens are issued\n * tokenTypeId - Corresponds to the two token types:\n * 1 => Tracker Token : NFT that map to list of TokenIds (NET) and ProductIds (CarbonTracker)\n * 2 => Product Token : Fungible tokens issued to each trackerId\n * sourceId - id of the source tracker or product token details\n * issuedBy - Address of transaction runner\n * issuedFrom - Address of dealer issuing this token\n * metadata - information stored about the product (e.g., unit information, source location, production dates )\n * manifest - source information about the product\n * description - high level description about the product (e.g., name)\n */\n struct TokenDetails {\n uint256 tokenId;\n uint8 tokenTypeId;\n uint256 sourceId;\n address issuedBy;\n address issuedFrom;\n string metadata;\n string manifest;\n //string description;\n }\n\n mapping(uint256 => TokenDetails) public _tokenDetails;\n //mapping(uint256 => mapping(address => uint256)) public _retiredBalances;\n\n mapping(uint256 => Tracker.CarbonTrackerDetails) private _trackerData;\n //mapping(uint256 => uint256) private _totalProductAmounts;\n mapping(uint256 => Tracker.CarbonTrackerMappings) private _trackerMappings;\n mapping(uint256 => Tracker.ProductDetails) public _productData;\n\n // Counts number of unique token IDs (auto-incrementing)\n Counters.Counter private _numOfUniqueTokens;\n Counters.Counter private _numOfUniqueTrackers;\n Counters.Counter private _numOfUniqueProducts;\n\n mapping(uint256 => uint256) private _lockedNET;\n //amount of tokenId locked into the contract. In most cases this is the amount of token issued to the contract address.\n //However tokens can be issued to contract before they are assiged to a tracker token using NET parent issue/transfer functions to send tokens to the Carbon Tracker contract addresss.\n // NET need to be assigned to tracker by calling track() for new , and trackUpdate() for exisitng carbon tracker.\n // WARNING if the above is not done tokens issued to the contract can be linked to any unissued trackerId of the CarbonTracker contract by an auditor.\n // The safest way to assing NET to tracker is using a NET function that call the CarbonTrackerContract, i.e,., issueAndTrack().\n\n mapping(address => mapping(address => bool)) internal isAuditorApproved;\n // map address of auditor and trackee to boolean enforcing isAuditorApproved in isAuditor modifier\n mapping(address => bool) internal approvedAuditorsOnly;\n // map address of trackee to boolean used to restrict audit funcitons to isAuditorApproved\n\n mapping(address => mapping(address => uint32)) private tokenTransferNonce;\n\n mapping(address => bool) public approveProductTransfer;\n\n uint256 public decimalsCt; // decimals for distribution of shared NET within CarbonTracker contract\n\n event TrackTokens(\n uint256 indexed trackerId,\n address indexed operator,\n uint256[] tokenIds,\n uint256[] tokenAmounts\n );\n\n event ProductsIssued(\n uint256 indexed trackerId,\n uint256[] productIds,\n uint256[] productAmounts\n );\n event TransferProducts(\n address indexed sender,\n uint256[] productIds,\n uint256[] productAmounts\n );\n\n event TrackProduct(\n uint256 indexed trackerId,\n address indexed operator,\n uint256 productId,\n uint256 productAmount\n );\n\n event VerifierApproval(\n address indexed auditor,\n address indexed trackee,\n bool approve,\n uint256 date\n );\n\n event ApproveProductTransfer(\n address indexed receiver,\n bool approve,\n uint256 date\n );\n\n constructor(address _net, address _admin) ERC1155(\"\") {\n net = NetEmissionsTokenNetwork(_net);\n netAddress = _net;\n decimalsCt = 1000000;\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n }\n\n modifier isAuditor(uint256 trackerId) {\n require(\n __isAuditor(_trackerData[trackerId].trackee),\n \"CLM8::isAuditor: msg.sender is not an approved auditor for this trackerId\"\n );\n require(\n _trackerData[trackerId].trackee != msg.sender,\n \"CLM8::isAuditor: msg.sender is the same as the trackee of trackerId\"\n );\n _;\n }\n\n function __isAuditor(address _trackee) internal view returns (bool) {\n return\n (net.isAuditor(msg.sender) || msg.sender == netAddress) &&\n (// require isAuditorApproved?\n (approvedAuditorsOnly[_trackee] &&\n isAuditorApproved[msg.sender][_trackee]) ||\n !approvedAuditorsOnly[_trackee]); // otherwise permit any auditor\n }\n\n function _tokenExists(uint256 tokenId) internal view {\n require(\n _tokenDetails[tokenId].tokenId != 0,\n \"CLM8::_tokenExists: tokenId does not exist\"\n );\n }\n\n modifier notIssued(uint256 trackerId) {\n _tokenExists(_trackerData[trackerId].tokenId);\n require(\n _tokenDetails[_trackerData[trackerId].tokenId].issuedBy ==\n address(0),\n \"CLM8::notIssued: trackerId has already been issued\"\n );\n _;\n }\n\n function _isIssued(uint256 trackerId) internal view {\n require(\n _tokenDetails[_trackerData[trackerId].tokenId].issuedBy !=\n address(0),\n \"CLM8::_isIssued: trackerId is not issued\"\n );\n }\n\n function _isOwner(uint256 trackerId) internal view {\n require(\n super.balanceOf(msg.sender, _trackerData[trackerId].tokenId) == 1,\n \"CLM8::_isOwner: msg.sender does not own this trackerId\"\n );\n }\n\n modifier isAuditorOrTrackee(uint256 trackerId) {\n require(\n __isAuditor(_trackerData[trackerId].trackee) ||\n _trackerData[trackerId].trackee == msg.sender,\n \"CLM8::_isAuditorOrTrackee: msg.sender is not the auditor or is not the assigned trackee of trackerId\"\n );\n _;\n }\n\n modifier isIndustry(address industry) {\n require(\n net.isIndustry(industry),\n \"CLM8::isIndustry: address must be a registered industry\"\n );\n _;\n }\n\n modifier onlyAdmin() {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"CLM8::onlyAdmin: msg.sender is not an admin\"\n );\n _;\n }\n\n modifier consumerOrIndustry(address _address) {\n if (_address != address(0)) {\n // if not burning require sender to be consumerOrDealer\n require(\n net._consumerOrDealer(_address),\n \"CLM8::consumerOrDealer: address is not a registered consumer, industry or dealer\"\n );\n }\n _;\n }\n\n function supportsInterface(bytes4 interfaceId)\n public\n view\n virtual\n override(ERC1155, ERC1155Receiver, AccessControl)\n returns (bool)\n {\n return\n interfaceId == type(IAccessControl).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev hook before handling tokenTransfers\n * Used to prevent locked product tokens from being transfered from the contract address\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override consumerOrIndustry(to) {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n bool productTransferVerified; // only verified product transfer once\n for (uint256 i = 0; i < ids.length; i++) {\n if (_tokenDetails[ids[i]].tokenTypeId == 2) {\n if (approveProductTransfer[to] && !productTransferVerified) {\n bytes32 messageHash = getTransferHash(\n from,\n to,\n ids,\n amounts\n );\n productTransferVerified = messageHash.verifySignature(\n data,\n to\n );\n require(\n productTransferVerified,\n \"CLM8::_beforeTokenTransfer: receiver has not approved the transaction\"\n );\n //increment the nonce once transaction has been confirmed\n tokenTransferNonce[from][to]++;\n }\n }\n //if(to==address(0)){_retiredBalances[ids[i]][from]=amounts[i];}\n }\n }\n\n /**\n * @dev initialize a tracker Token for trackee. Any address can initilize a tracker. However, only auditors can initialize a tracker with emission tokens\n * @param trackee - address of the registered industry of the trackee\n * @param netIds - array of ids of tracked tokens from NET (direct/indirect/offsets)\n * @param netAmounts - array of incoming token id amounts (direct/indirect/offsets) matching each carbon token\n * @param metadata - information about the tracker\n * @param manifest - info about the origin of the tracker (e.g. source file)\n * param description - about the tracker\n */\n function track(\n address trackee,\n uint256[] memory netIds,\n uint256[] memory netAmounts,\n string memory metadata,\n string memory manifest\n )\n public\n //,string memory description\n isIndustry(trackee) // limit new tracker to industry addresses\n {\n _numOfUniqueTrackers.increment();\n // create tracker details\n uint256 trackerId = _numOfUniqueTrackers.current();\n _trackerData[trackerId].trackerId = trackerId;\n _trackerData[trackerId].trackee = trackee;\n\n // issue token for tracker (NFT) but do not mint\n _issue(\n address(0), //do not set issued address until token is minted\n tx.origin,\n trackee,\n 1, //tokenTypeId\n 0, //tokenAmount set to 0. Only mint this in final issue() function\n trackerId,\n metadata,\n manifest\n //,description\n );\n _trackerData[trackerId].tokenId = _numOfUniqueTokens.current();\n\n // add tokens if provided\n if (netIds.length > 0) {\n return _trackTokens(trackerId, netIds, netAmounts);\n } else {\n //emit event event to single tracker was created\n emit TrackTokens(trackerId, msg.sender, netIds, netAmounts);\n }\n }\n\n /**\n * @dev update a tracker Token\n * @param trackerId of the token\n * see tracker() function for description of other inputs\n **/\n function trackUpdate(\n uint256 trackerId,\n uint256[] memory netIds,\n uint256[] memory netAmounts,\n string memory metadata,\n string memory manifest\n )\n public\n //,string memory description\n notIssued(trackerId)\n {\n if (bytes(metadata).length > 0) {\n _tokenDetails[_trackerData[trackerId].tokenId].metadata = metadata;\n }\n if (bytes(manifest).length > 0) {\n _tokenDetails[_trackerData[trackerId].tokenId].manifest = manifest;\n }\n /*if (bytes(description).length > 0) {\n _tokenDetails[_trackerData[trackerId].tokenId].description = description;\n }*/\n _trackTokens(trackerId, netIds, netAmounts);\n }\n\n /**\n * @dev updated token data assinged to tracker\n * used by track() and trackerUpdate()\n **/\n function _trackTokens(\n uint256 trackerId,\n uint256[] memory tokenIds,\n uint256[] memory tokenAmounts\n ) internal isAuditor(_trackerData[trackerId].trackerId) {\n require(\n tokenAmounts.length == tokenIds.length,\n \"CLM8::_trackTokens: tokenAmounts and tokenIds are not the same length\"\n );\n // create trcker Mappings to store tokens (and product) info\n Tracker.CarbonTrackerMappings\n storage trackerMappings = _trackerMappings[\n _trackerData[trackerId].trackerId\n ];\n\n for (uint256 i = 0; i < tokenIds.length; i++) {\n // get available and retired token balances issued to the trackerAddress.\n (uint256 available, uint256 retired) = net.getAvailableAndRetired(\n address(this),\n tokenIds[i]\n );\n\n uint8 tokenTypeId = net.getTokenTypeId(tokenIds[i]);\n uint256 balance;\n\n if (tokenTypeId == 3) {\n // if AEC use retired amount\n balance = retired;\n } else {\n // otherwise balance is what is available to the contract\n balance = available;\n }\n\n // subtract previous token amount locked to contract\n _lockedNET[tokenIds[i]] = _lockedNET[tokenIds[i]].sub(\n trackerMappings.amount[tokenIds[i]]\n );\n\n require(\n msg.sender == netAddress ||\n balance.sub(_lockedNET[tokenIds[i]]) >= tokenAmounts[i],\n \"CLM8::_trackTokens: one of the tokenAmounts is greater than the balance of the tracker contract\"\n );\n\n _lockedNET[tokenIds[i]] = _lockedNET[tokenIds[i]].add(\n tokenAmounts[i]\n );\n\n tokenIds[i].updateIndexAndAmount(\n tokenAmounts[i],\n trackerMappings.tokenIds,\n trackerMappings.idIndex,\n trackerMappings.amount\n );\n }\n emit TrackTokens(trackerId, msg.sender, tokenIds, tokenAmounts);\n }\n\n /**\n * @dev add to (or update) products mapped to a trackerId.\n * @param trackerId to assign products\n * @param productAmounts - amount of products. Used for weighted distribution of emissino for multiproduct tracker\n * @param metadata - descriptive attributes like units and unitAmount if different from _productData[productId].issued\n * @param manifests - info about the origin of the issued product\n * param descriptions - description of product - e.g. name\n **/\n function issueProducts(\n uint256 trackerId,\n uint256[] memory productIds,\n uint256[] memory productAmounts,\n string[] memory metadata,\n string[] memory manifests\n )\n public\n //,string[] memory descriptions\n notIssued(trackerId)\n isAuditor(trackerId)\n {\n //uint256[] memory productIds;\n Tracker.CarbonTrackerDetails storage trackerData = _trackerData[\n trackerId\n ];\n require(\n productAmounts.length == productIds.length,\n \"CLM8::issueProducts: productIds and productAmounts arrays are not the same length\"\n );\n require(\n productAmounts.length == metadata.length,\n \"CLM8::issueProducts: productIds and metadata arrays are not the same length\"\n );\n require(\n productAmounts.length == manifests.length,\n \"CLM8::issueProducts: productIds and manifest arrays are not the same length\"\n );\n /*require(\n productAmounts.length == descriptions.length,\n \"CLM8::issueProducts: productIds and descriptions arrays are not the same length\"\n );*/\n for (uint256 i = 0; i < productAmounts.length; i++) {\n if (productIds[i] == 0) {\n // create a new productId\n _numOfUniqueProducts.increment();\n productIds[i] = _numOfUniqueProducts.current();\n // issue token for products\n _issue(\n msg.sender,\n msg.sender,\n address(this), // issue product Token to tracker Address\n 2, //tokenTypeId\n productAmounts[i], //tokenAmount for Carbon Tracker (NFT) = 1\n productIds[i],\n metadata[i],\n manifests[i]\n //,descriptions[i]\n );\n\n _productData[productIds[i]].tokenId = _numOfUniqueTokens\n .current();\n _productData[productIds[i]].productId = productIds[i];\n _productData[productIds[i]].trackerId = trackerId;\n } else {\n _tokenExists(_productData[productIds[i]].tokenId);\n require(\n _tokenDetails[_productData[productIds[i]].tokenId]\n .issuedBy == msg.sender,\n \"CLM8::issueProducts: msg.sender attempt to modify productId it did not issue\"\n );\n if (productAmounts[i] > _productData[productIds[i]].issued) {\n //mint more products\n super._mint(\n address(this),\n _productData[productIds[i]].tokenId,\n productAmounts[i].sub(\n _productData[productIds[i]].issued\n ),\n \"\"\n );\n } else {\n //burn excess products\n super._burn(\n address(this),\n _productData[productIds[i]].tokenId,\n _productData[productIds[i]].issued.sub(\n productAmounts[i]\n )\n );\n }\n //subtract previously stored productAmount from total.\n trackerData.totalProductAmounts = trackerData\n .totalProductAmounts\n .sub(_productData[productIds[i]].issued);\n\n if (bytes(metadata[i]).length > 0) {\n _tokenDetails[_productData[productIds[i]].tokenId]\n .metadata = metadata[i];\n }\n if (bytes(manifests[i]).length > 0) {\n _tokenDetails[_productData[productIds[i]].tokenId]\n .manifest = manifests[i];\n }\n /*if (bytes(descriptions[i]).length > 0) {\n _tokenDetails[_productData[productIds[i]].tokenId].description = descriptions[i];\n }*/\n }\n\n _productData[productIds[i]].issued = productAmounts[i];\n _productData[productIds[i]].available = productAmounts[i];\n\n trackerData.totalProductAmounts = trackerData\n .totalProductAmounts\n .add(productAmounts[i]);\n }\n emit ProductsIssued(trackerId, productIds, productAmounts);\n }\n\n /**\n * @dev issue token\n **/\n function _issue(\n address _issuedBy,\n address _issuedFrom,\n address _issuedTo,\n uint8 _tokenTypeId,\n uint256 _quantity,\n uint256 _sourceId,\n string memory metadata,\n string memory manifest //,string memory description\n ) internal {\n // increment trackerId\n _numOfUniqueTokens.increment();\n uint256 tokenId = _numOfUniqueTokens.current();\n // create token details\n\n _tokenDetails[tokenId].tokenId = tokenId;\n _tokenDetails[tokenId].sourceId = _sourceId;\n _tokenDetails[tokenId].tokenTypeId = _tokenTypeId;\n _tokenDetails[tokenId].issuedBy = _issuedBy;\n _tokenDetails[tokenId].issuedFrom = _issuedFrom;\n _tokenDetails[tokenId].metadata = metadata;\n _tokenDetails[tokenId].manifest = manifest;\n //_tokenDetails[tokenId].description = description;\n\n if (_tokenTypeId != 1) {\n super._mint(_issuedTo, tokenId, _quantity, \"\");\n }\n }\n\n /**\n * @dev transfer product\n * @param productIds to transfer\n * @param amounts of productIds to transfer\n * @param to receiver's address\n **/\n function transferProducts(\n address to,\n uint256[] memory productIds,\n uint256[] memory amounts,\n bytes memory data\n ) public {\n uint256[] memory tokenIds = new uint256[](productIds.length);\n for (uint256 i = 0; i < productIds.length; i++) {\n uint256 available = _productData[productIds[i]].available;\n require(\n available >= amounts[i],\n \"CLM8::_beforeTokenTransfer: product amount exceeds what is available to the contract\"\n );\n _isIssued(_productData[productIds[i]].trackerId);\n _isOwner(_productData[productIds[i]].trackerId);\n //update avaiable amount of productId;\n _productData[productIds[i]].available = available.sub(amounts[i]);\n tokenIds[i] = _productData[productIds[i]].tokenId;\n }\n if (to != address(this)) {\n super._safeBatchTransferFrom(\n address(this),\n to,\n tokenIds,\n amounts,\n data\n );\n }\n emit TransferProducts(msg.sender, productIds, amounts);\n }\n\n /**\n * @dev track a product to an new trackerId\n * @param from address of the productId nbeing tracker\n * in this function the owner of as trackerId, or an auditor, assigns products received from other carbon tracker tokens\n * if from address is different from msg.sender\n **/\n function trackProduct(\n address from,\n uint256 trackerId,\n uint256 productId,\n uint256 productAmount\n ) public notIssued(trackerId) isAuditorOrTrackee(trackerId) {\n require(\n trackerId != _productData[productId].trackerId,\n \"CLM8::trackProduct: product's trackerId can not be the same as the trackerId\"\n );\n\n uint256 previousProductAmount = _trackerMappings[trackerId]\n .productAmount[productId];\n uint256 transferAmount;\n if (productAmount > previousProductAmount) {\n transferAmount = productAmount.sub(previousProductAmount);\n // transfer more product to contract\n bool operatorApproved = super.isApprovedForAll(from, msg.sender);\n if (__isAuditor(from) && operatorApproved == false) {\n // approve auditor to transfer tokens for from address\n super._setApprovalForAll(from, msg.sender, true);\n }\n // if from address is owner of the trackerId of the productId\n if (\n super.balanceOf(\n from,\n _trackerData[_productData[productId].trackerId].tokenId\n ) == 1\n ) {\n uint256 availBalance = super.balanceOf(\n from,\n _productData[productId].tokenId\n );\n // compare availBalance to residual transferAmount\n if (availBalance >= transferAmount) {\n super.safeTransferFrom(\n from,\n address(this),\n _productData[productId].tokenId,\n transferAmount,\n \"\"\n );\n } else {\n super.safeTransferFrom(\n from,\n address(this),\n _productData[productId].tokenId,\n availBalance,\n \"\"\n );\n transferAmount = transferAmount.sub(availBalance);\n // if less try transfering from tracker owned by the msg.sender\n // this will fail if msg.sender != from\n uint256[] memory productIds = new uint256[](1);\n uint256[] memory productAmounts = new uint256[](1);\n productIds[0] = productId;\n productAmounts[0] = productAmount;\n transferProducts(\n address(this),\n productIds,\n productAmounts,\n \"0x00\"\n );\n }\n } else {\n super.safeTransferFrom(\n from,\n address(this),\n _productData[productId].tokenId,\n transferAmount,\n \"\"\n );\n }\n\n if (__isAuditor(from) && operatorApproved == false) {\n // remove approval to transfer tokens for from address\n super._setApprovalForAll(from, msg.sender, false);\n }\n } else {\n transferAmount = previousProductAmount.sub(productAmount);\n //refund excess amount previously locked to contract\n super.safeTransferFrom(\n address(this),\n from,\n _productData[productId].tokenId,\n transferAmount,\n \"\"\n );\n }\n Tracker.CarbonTrackerMappings\n storage trackerMappings = _trackerMappings[trackerId];\n productId.updateIndexAndAmount(\n productAmount,\n trackerMappings.productIds,\n trackerMappings.productIdIndex,\n trackerMappings.productAmount\n );\n emit TrackProduct(trackerId, msg.sender, productId, productAmount);\n }\n\n /**\n * Issue the tracker token\n **/\n function issue(uint256 trackerId)\n public\n notIssued(trackerId)\n isAuditor(trackerId)\n {\n super._mint(\n _trackerData[trackerId].trackee,\n _trackerData[trackerId].tokenId,\n 1,\n \"\"\n );\n _tokenDetails[_trackerData[trackerId].tokenId].issuedBy = msg.sender;\n }\n\n /**\n * @dev approve verifier for trackee as msg.sender\n * @param approve (true) or remove (false)\n */\n function setApprovedAuditorsOnly(bool approve)\n external\n isIndustry(msg.sender)\n {\n approvedAuditorsOnly[msg.sender] = approve;\n }\n\n /**\n * @dev approve verifier for trackee as msg.sender\n * @param verifier to be approved or removed\n * @param approve (true) or remove (false)\n */\n function approveVerifier(address verifier, bool approve)\n external\n isIndustry(msg.sender)\n {\n require(\n net.isAuditor(verifier) || !approve,\n \"CLM8::approveVerifier: address is not a registered emissions auditor\"\n );\n require(\n verifier != msg.sender,\n \"CLM8::approveVerifier: auditor cannot be msg.sender\"\n );\n isAuditorApproved[verifier][msg.sender] = approve;\n emit VerifierApproval(verifier, msg.sender, approve, block.timestamp);\n }\n\n /*\n @dev function requires receiver address to pre-approve product transfers\n @param approve bool to tollge tx verificion on or off\n */\n function setApproveProductTransfer(bool approve)\n external\n consumerOrIndustry(msg.sender)\n {\n approveProductTransfer[msg.sender] = approve;\n emit ApproveProductTransfer(msg.sender, approve, block.timestamp);\n }\n\n /**\n * @dev Returns keccak256 hash of transaction request\n */\n function getTransferHash(\n address _from,\n address _to,\n uint256[] memory _ids,\n uint256[] memory _amounts\n ) public view returns (bytes32) {\n return\n _from._getTransferHash(\n _to,\n _ids,\n _amounts,\n tokenTransferNonce[_from][_to]\n );\n }\n\n /** Below are public view functions **/\n\n struct NetTotals {\n uint256 rec;\n uint256 offsets;\n uint256 emissions;\n }\n\n /**\n * @dev returns the details of a given trackerId\n */\n function getTrackerDetails(uint256 trackerId)\n public\n view\n returns (\n Tracker.CarbonTrackerDetails memory,\n uint256[] memory,\n uint256[] memory,\n uint256[] memory,\n uint256[] memory,\n NetTotals memory\n )\n {\n uint256[] memory tokenAmounts = new uint256[](\n _trackerMappings[trackerId].tokenIds.length\n );\n for (\n uint256 i = 0;\n i < _trackerMappings[trackerId].tokenIds.length;\n i++\n ) {\n tokenAmounts[i] = _trackerMappings[trackerId].amount[\n _trackerMappings[trackerId].tokenIds[i]\n ];\n }\n uint256[] memory productAmounts = new uint256[](\n _trackerMappings[trackerId].productIds.length\n );\n for (\n uint256 i = 0;\n i < _trackerMappings[trackerId].productIds.length;\n i++\n ) {\n productAmounts[i] = _trackerMappings[trackerId].productAmount[\n _trackerMappings[trackerId].productIds[i]\n ];\n }\n NetTotals memory totals = _getTotalEmissions(trackerId);\n return (\n _trackerData[trackerId],\n _trackerMappings[trackerId].tokenIds,\n tokenAmounts,\n _trackerMappings[trackerId].productIds,\n productAmounts,\n totals\n );\n }\n\n function _getTotalEmissions(uint256 trackerId)\n internal\n view\n returns (NetTotals memory)\n {\n uint256[] memory tokenIds = _trackerMappings[trackerId].tokenIds;\n NetTotals memory totals;\n uint256 netAmount;\n uint8 tokenTypeId;\n for (uint256 i = 0; i < tokenIds.length; i++) {\n netAmount = decimalsCt.mul(\n _trackerMappings[trackerId].amount[tokenIds[i]]\n );\n tokenTypeId = net.getTokenTypeId(tokenIds[i]);\n if (tokenTypeId == 3) {\n totals.emissions = totals.emissions.add(netAmount);\n } else if (tokenTypeId == 2) {\n totals.offsets = totals.offsets.add(netAmount);\n } else if (tokenTypeId == 1) {\n totals.rec = totals.rec.add(netAmount);\n }\n }\n return _getTotalsTracked(totals, trackerId);\n }\n\n function _getTotalsTracked(NetTotals memory totals, uint256 trackerId)\n private\n view\n returns (NetTotals memory)\n {\n uint256[] memory productIds = _trackerMappings[trackerId].productIds;\n for (uint256 i = 0; i < productIds.length; i++) {\n uint256 sourceTrackerId = _productData[productIds[i]].trackerId;\n if (_trackerData[sourceTrackerId].totalProductAmounts > 0) {\n NetTotals memory totalsTracked = _getTotalEmissions(\n sourceTrackerId\n );\n totals.emissions = totals.emissions.add(\n _trackerMappings[trackerId]\n .productAmount[productIds[i]]\n .mul(totalsTracked.emissions)\n .div(_trackerData[sourceTrackerId].totalProductAmounts)\n );\n totals.offsets = totals.offsets.add(\n _trackerMappings[trackerId]\n .productAmount[productIds[i]]\n .mul(totalsTracked.offsets)\n .div(_trackerData[sourceTrackerId].totalProductAmounts)\n );\n totals.rec = totals.rec.add(\n _trackerMappings[trackerId]\n .productAmount[productIds[i]]\n .mul(totalsTracked.rec)\n .div(_trackerData[sourceTrackerId].totalProductAmounts)\n );\n }\n }\n return totals;\n }\n\n /**\n * @dev returns number of unique trackers\n */\n function getNumOfUniqueTrackers() public view returns (uint256) {\n return _numOfUniqueTrackers.current();\n }\n\n /**\n * @dev returns number of unique trackers\n */\n function getNumOfUniqueProducts() public view returns (uint256) {\n return _numOfUniqueProducts.current();\n }\n\n /**\n * @dev returns number of unique trackers\n */\n function getNumOfUniqueTokens() public view returns (uint256) {\n return _numOfUniqueTokens.current();\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: address zero is not a valid owner\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _balances[id][to] += amount;\n emit TransferSingle(operator, address(0), to, id, amount);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `from`\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `from` must have at least `amount` tokens of token type `id`.\n */\n function _burn(\n address from,\n uint256 id,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n\n emit TransferSingle(operator, from, address(0), id, amount);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(\n address from,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n }\n\n emit TransferBatch(operator, from, address(0), ids, amounts);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC1155: setting approval status for self\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver.onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ERC1155Receiver.sol\";\n\n/**\n * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens.\n *\n * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be\n * stuck.\n *\n * @dev _Available since v3.1._\n */\ncontract ERC1155Holder is ERC1155Receiver {\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155Received.selector;\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] memory,\n uint256[] memory,\n bytes memory\n ) public virtual override returns (bytes4) {\n return this.onERC1155BatchReceived.selector;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155Receiver.sol\";\nimport \"../../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\nabstract contract ERC1155Receiver is ERC165, IERC1155Receiver {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n" + }, + "solidity/NetEmissionsTokenNetwork.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"./CarbonTracker.sol\";\n\ncontract NetEmissionsTokenNetwork is ERC1155, AccessControl {\n using SafeMath for uint256;\n using Counters for Counters.Counter;\n\n bool public limitedMode; // disables some features like arbitrary token transfers and issuing without proposals\n address private timelock; // DAO contract that executes proposals to issue tokens after a successful vote\n\n // Generic dealer role for registering/unregistering consumers\n bytes32 public constant REGISTERED_DEALER = keccak256(\"REGISTERED_DEALER\");\n // Token type specific roles\n bytes32 public constant REGISTERED_REC_DEALER =\n keccak256(\"REGISTERED_REC_DEALER\");\n bytes32 public constant REGISTERED_OFFSET_DEALER =\n keccak256(\"REGISTERED_OFFSET_DEALER\");\n bytes32 public constant REGISTERED_EMISSIONS_AUDITOR =\n keccak256(\"REGISTERED_EMISSIONS_AUDITOR\");\n // Consumer role\n bytes32 public constant REGISTERED_CONSUMER =\n keccak256(\"REGISTERED_CONSUMER\");\n // Industry role (admin/dealer assigned)\n bytes32 public constant REGISTERED_INDUSTRY =\n keccak256(\"REGISTERED_INDUSTRY\");\n\n /**\n * @dev Structure of all tokens issued in this contract\n * tokenId - Auto-increments whenever new tokens are issued\n * tokenTypeId - Corresponds to the three token types:\n * 1 => Renewable Energy Certificate\n * 2 => Carbon Emissions Offset\n * 3 => Audited Emissions\n * issuedBy - Address of transaction runner\n * issuedFrom - Address of dealer issuing this token\n * issuee - Address of original issued recipient this token\n * fromDate - Unix timestamp\n * thruDate - Unix timestamp\n * dateCreated - Unix timestamp\n */\n struct CarbonTokenDetails {\n uint256 tokenId;\n uint8 tokenTypeId;\n address issuedBy;\n uint160 issuedFrom;\n address issuedTo;\n uint256 fromDate;\n uint256 thruDate;\n uint256 dateCreated;\n string metadata;\n string manifest;\n string description;\n uint256 totalIssued;\n uint256 totalRetired;\n }\n\n // Counts number of unique token IDs (auto-incrementing)\n Counters.Counter private _numOfUniqueTokens;\n\n // Token metadata and retired balances\n mapping(uint256 => CarbonTokenDetails) private _tokenDetails;\n mapping(uint256 => mapping(address => uint256)) private _retiredBalances;\n\n // Events\n event TokenCreated(\n uint256 availableBalance,\n uint256 retiredBalance,\n uint256 tokenId,\n uint8 tokenTypeId,\n address indexed issuedBy,\n uint160 indexed issuedFrom,\n address indexed issuedTo,\n uint256 fromDate,\n uint256 thruDate,\n uint256 dateCreated,\n string metadata,\n string manifest,\n string description\n );\n event TokenRetired(\n address indexed account,\n uint256 tokenId,\n uint256 amount\n );\n event RegisteredConsumer(address indexed account);\n event UnregisteredConsumer(address indexed account);\n event RegisteredDealer(address indexed account);\n event UnregisteredDealer(address indexed account);\n event RegisteredIndustry(address indexed account);\n event UnregisteredIndustry(address indexed account);\n\n constructor(address _admin) ERC1155(\"\") {\n // Allow dealers to register consumers\n _setRoleAdmin(REGISTERED_CONSUMER, REGISTERED_DEALER);\n\n // Set-up admin\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n _setupRole(REGISTERED_DEALER, _admin);\n _setupRole(REGISTERED_REC_DEALER, _admin);\n _setupRole(REGISTERED_OFFSET_DEALER, _admin);\n _setupRole(REGISTERED_EMISSIONS_AUDITOR, _admin);\n _setupRole(REGISTERED_INDUSTRY, _admin);\n\n // initialize\n timelock = address(0);\n\n limitedMode = false;\n }\n\n modifier onlyAdmin() {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"CLM8::onlyAdmin: msg.sender not the admin\"\n );\n _;\n }\n\n modifier consumerOrDealer(address from, address to) {\n if (from != address(0)) {\n // if not minting require sender to be consumerOrDealer\n require(\n _consumerOrDealer(from),\n \"CLM8::consumerOrDealer: sender not a consumer or a dealer\"\n );\n }\n if (to != address(0)) {\n // if not burning require receiver is consumerOrDealer\n require(\n _consumerOrDealer(to),\n \"CLM8::consumerOrDealer: recipient must be consumer, dealer or industry\"\n );\n }\n _;\n }\n\n modifier onlyDealer() {\n _onlyDealer();\n _;\n }\n\n /**\n * @dev Returns `true` if hasRole of dealer\n */\n function _onlyDealer() internal view {\n /*\n bool isRecDealer = hasRole(REGISTERED_REC_DEALER, msg.sender);\n bool isCeoDealer = hasRole(REGISTERED_OFFSET_DEALER, msg.sender);\n bool isAeDealer = hasRole(REGISTERED_EMISSIONS_AUDITOR, msg.sender);\n */\n require(\n //hasRole(REGISTERED_REC_DEALER, msg.sender) ||\n //hasRole(REGISTERED_OFFSET_DEALER, msg.sender) ||\n //hasRole(REGISTERED_EMISSIONS_AUDITOR, msg.sender) ||\n // the below will achieve the same as the above\n hasRole(REGISTERED_DEALER, msg.sender),\n \"CLM8::onlyDealer: msg.sender not a dealer\"\n );\n }\n\n /**\n * @dev Returns `true` if hasRole of dealer, industry or consumer\n */\n function _consumerOrDealer(address entity) public view returns (bool) {\n // check for one role and return if true if true\n // before checking the next to minimize gas\n if (\n hasRole(REGISTERED_DEALER, entity) ||\n hasRole(REGISTERED_CONSUMER, entity) ||\n hasRole(REGISTERED_INDUSTRY, entity)\n ) return true;\n return false;\n }\n\n /**\n * @dev returns true if the tokenId exists\n */\n function tokenExists(uint256 tokenId) private view returns (bool) {\n if (_numOfUniqueTokens.current() >= tokenId) return true;\n return false; // no matching tokenId\n }\n\n /**\n * @dev returns true if the tokenTypeId is valid\n */\n function tokenTypeIdIsValid(uint8 tokenTypeId) private pure returns (bool) {\n if ((tokenTypeId > 0) && (tokenTypeId <= 3)) {\n return true;\n }\n return false; // no matching tokenId\n }\n\n /**\n * @dev returns number of unique tokens\n */\n function getNumOfUniqueTokens() public view returns (uint256) {\n return _numOfUniqueTokens.current();\n }\n\n function supportsInterface(bytes4 interfaceId)\n public\n view\n virtual\n override(ERC1155, AccessControl)\n returns (bool)\n {\n return\n interfaceId == type(IAccessControl).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev hook to prevent transfers from non-admin account if limitedMode is on\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override consumerOrDealer(from, to) {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n // TO-DO this could be set as a modifier ...\n require(\n (from != to),\n \"CLM8::_beforeTokenTransfer: sender and receiver cannot be the same\"\n );\n for (uint256 i = 0; i < ids.length; i++) {\n CarbonTokenDetails storage token = _tokenDetails[ids[i]];\n // disable most transfers if limitedMode is on\n if (limitedMode) {\n // allow retiring/burning one's tokens\n if (to == address(0)) {\n continue;\n }\n\n // for tokenType 1 and 2, only the timelock and DAO can transfer/issue\n // for tokenType 3, only emissions auditors can transfer/issue\n // (and they are automatically retired right after)\n if (token.tokenTypeId == 1 || token.tokenTypeId == 2) {\n require(\n operator == timelock ||\n hasRole(DEFAULT_ADMIN_ROLE, operator),\n \"CLM8::_beforeTokenTransfer(limited): only admin and DAO can transfer tokens\"\n );\n } else if (token.tokenTypeId == 3) {\n require(\n hasRole(REGISTERED_EMISSIONS_AUDITOR, operator),\n \"CLM8::_beforeTokenTransfer(limited): only emissions auditors can issue audited emissions\"\n );\n }\n }\n }\n }\n\n /**\n * @dev External function to mint an amount of a token\n * Only authorized dealer of associated token type can call this function\n * @param quantity of the token to mint For ex: if one needs 100 full tokens, the caller\n * should set the amount as (100 * 10^4) = 1,000,000 (assuming the token's decimals is set to 4)\n */\n function issue(\n uint160 issuedFrom,\n address issuedTo,\n uint8 tokenTypeId,\n uint256 quantity,\n uint256 fromDate,\n uint256 thruDate,\n string memory metadata,\n string memory manifest,\n string memory description\n ) public onlyDealer {\n return\n _issue(\n msg.sender, // issuedBy\n issuedFrom,\n issuedTo,\n tokenTypeId,\n quantity,\n fromDate,\n thruDate,\n metadata,\n manifest,\n description\n );\n }\n\n /**\n * @dev Issue function for DAO (on limited mode) or admin to manually pass issuer\n * Must be called from Timelock contract through a successful proposal\n * or by admin if limited mode is set to false\n */\n function issueOnBehalf(\n address issuedBy,\n uint160 issuedFrom,\n address issuedTo,\n uint8 tokenTypeId,\n uint256 quantity,\n uint256 fromDate,\n uint256 thruDate,\n string memory metadata,\n string memory manifest,\n string memory description\n ) public {\n require(\n (msg.sender == timelock) || hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"CLM8::issueOnBehalf: call must come from DAO or admin\"\n );\n\n return\n _issue(\n issuedBy,\n issuedFrom,\n issuedTo,\n tokenTypeId,\n quantity,\n fromDate,\n thruDate,\n metadata,\n manifest,\n description\n );\n }\n\n function issueAndTrack(\n uint160 issuedFrom,\n address issuedTo,\n address trackerAddress,\n uint256 trackerId,\n uint8 tokenTypeId,\n uint256 quantity,\n uint256 fromDate,\n uint256 thruDate,\n string memory metadata,\n string memory manifest,\n string memory description\n ) public onlyDealer {\n require(\n CarbonTracker(trackerAddress).netAddress() == address(this),\n \"CLM8::issueAndTrack: trackerAddress is not a child of this NET contract\"\n );\n uint256[] memory tokenIds = new uint256[](1);\n uint256[] memory tokenAmounts = new uint256[](1);\n\n _issue(\n msg.sender, // issuedBy\n issuedFrom,\n trackerAddress,\n tokenTypeId,\n quantity,\n fromDate,\n thruDate,\n metadata,\n manifest,\n description\n );\n tokenIds[0] = _numOfUniqueTokens.current();\n tokenAmounts[0] = quantity;\n if (trackerId == 0) {\n CarbonTracker(trackerAddress).track(\n issuedTo,\n tokenIds,\n tokenAmounts,\n \"\",\n \"\"\n //,\"\"\n );\n } else {\n CarbonTracker(trackerAddress).trackUpdate(\n trackerId,\n tokenIds,\n tokenAmounts,\n \"\",\n \"\"\n //,\"\"\n );\n }\n }\n\n function _issue(\n address _issuedBy,\n uint160 _issuedFrom,\n address _issuedTo,\n uint8 _tokenTypeId,\n uint256 _quantity,\n uint256 _fromDate,\n uint256 _thruDate,\n string memory _metadata,\n string memory _manifest,\n string memory _description\n ) internal {\n require(\n tokenTypeIdIsValid(_tokenTypeId),\n \"CLM8::_issue: tokenTypeId is invalid\"\n );\n\n if (limitedMode) {\n if (_tokenTypeId == 1 || _tokenTypeId == 2) {\n require(\n msg.sender == timelock,\n \"CLM8::_issue(limited): msg.sender not timelock\"\n );\n require(\n hasRole(DEFAULT_ADMIN_ROLE, _issuedTo),\n \"CLM8::_issue(limited): issuee not admin\"\n );\n require(\n hasRole(REGISTERED_REC_DEALER, _issuedBy) ||\n hasRole(REGISTERED_OFFSET_DEALER, _issuedBy),\n \"CLM8::_issue(limited): proposer not a registered dealer\"\n );\n } else if (_tokenTypeId == 3 || _tokenTypeId == 4) {\n require(\n hasRole(REGISTERED_EMISSIONS_AUDITOR, _issuedBy),\n \"CLM8::_issue(limited): issuer not a registered emissions auditor\"\n );\n }\n } else {\n if (_tokenTypeId == 1) {\n require(\n hasRole(REGISTERED_REC_DEALER, _issuedBy),\n \"CLM8::_issue: issuer not a registered REC dealer\"\n );\n } else if (_tokenTypeId == 2) {\n require(\n hasRole(REGISTERED_OFFSET_DEALER, _issuedBy),\n \"CLM8::_issue: issuer not a registered offset dealer\"\n );\n } else if (_tokenTypeId == 3 || _tokenTypeId == 4) {\n require(\n hasRole(REGISTERED_EMISSIONS_AUDITOR, _issuedBy),\n \"CLM8::_issue: issuer not a registered emissions auditor\"\n );\n // require(\n // hasRole(REGISTERED_EMISSIONS_AUDITOR, _issuer),\n // \"CLM8::_issue: issuer not a registered emissions auditor\"\n // );\n }\n }\n\n // increment token identifier\n _numOfUniqueTokens.increment();\n\n // create token details\n CarbonTokenDetails storage tokenInfo = _tokenDetails[\n _numOfUniqueTokens.current()\n ];\n\n tokenInfo.tokenId = _numOfUniqueTokens.current();\n tokenInfo.tokenTypeId = _tokenTypeId;\n tokenInfo.issuedBy = _issuedBy;\n tokenInfo.issuedFrom = _issuedFrom;\n tokenInfo.issuedTo = _issuedTo;\n tokenInfo.fromDate = _fromDate;\n tokenInfo.thruDate = _thruDate;\n tokenInfo.dateCreated = block.timestamp;\n tokenInfo.metadata = _metadata;\n tokenInfo.manifest = _manifest;\n tokenInfo.description = _description;\n tokenInfo.totalIssued = _quantity;\n tokenInfo.totalRetired = uint256(0);\n\n super._mint(_issuedTo, _numOfUniqueTokens.current(), _quantity, \"\");\n\n // retire audited emissions on mint\n if (_tokenTypeId == 3) {\n _retire(tokenInfo.issuedTo, tokenInfo.tokenId, _quantity);\n }\n\n // emit event with all token details and balances\n emit TokenCreated(\n _quantity,\n _retiredBalances[tokenInfo.tokenId][tokenInfo.issuedTo],\n tokenInfo.tokenId,\n tokenInfo.tokenTypeId,\n tokenInfo.issuedBy,\n tokenInfo.issuedFrom,\n tokenInfo.issuedTo,\n tokenInfo.fromDate,\n tokenInfo.thruDate,\n tokenInfo.dateCreated,\n tokenInfo.metadata,\n tokenInfo.manifest,\n tokenInfo.description\n );\n }\n\n /**\n * @dev mints more of an existing token\n * @param to reciepient of token\n * @param tokenId token to mint more of\n * @param quantity amount to mint\n */\n // To DO - this will increase _balances of to account\n // but will not update the totalIssued ?\n function mint(\n address to,\n uint256 tokenId,\n uint256 quantity\n ) external onlyAdmin {\n require(tokenExists(tokenId), \"CLM8::mint: tokenId does not exist\");\n require(\n !limitedMode,\n \"CLM8::mint: cannot mint new tokens in limited mode\"\n );\n super._mint(to, tokenId, quantity, \"\");\n }\n\n /**\n * @dev returns the token name for the given token as a string value\n * @param tokenId token to check\n */\n function getTokenType(uint256 tokenId)\n external\n view\n returns (string memory)\n {\n require(\n tokenExists(tokenId),\n \"CLM8::getTokenType: tokenId does not exist\"\n );\n CarbonTokenDetails storage token = _tokenDetails[tokenId];\n\n if (token.tokenTypeId == 1) {\n return \"Renewable Energy Certificate\";\n } else if (token.tokenTypeId == 2) {\n return \"Carbon Emissions Offset\";\n } else if (token.tokenTypeId == 3) {\n return \"Audited Emissions\";\n } else {\n return \"Token does not exist\";\n }\n }\n\n function getTokenTypeId(uint256 tokenId) external view returns (uint8) {\n return _tokenDetails[tokenId].tokenTypeId;\n }\n\n function getRetiredBalances(uint256 tokenId, address account)\n external\n view\n returns (uint256)\n {\n return _retiredBalances[tokenId][account];\n }\n\n /**\n * @dev returns the retired amount on a token\n * @param tokenId token to check\n */\n function getTokenRetiredAmount(address account, uint256 tokenId)\n public\n view\n returns (uint256)\n {\n require(\n tokenExists(tokenId),\n \"CLM8::getTokenRetiredAmount: tokenId does not exist\"\n );\n uint256 amount = _retiredBalances[tokenId][account];\n return amount;\n }\n\n /**\n * @dev sets the token to the retire state to disable transfers, mints and burns\n * @param tokenId token to set in pause state\n * Only contract owner can pause or resume tokens\n */\n function retire(uint256 tokenId, uint256 amount)\n external\n consumerOrDealer(msg.sender, address(0))\n {\n require(tokenExists(tokenId), \"CLM8::retire: tokenId does not exist\");\n // TO-DO do we need this require statement? super._burn sub() will require this ...\n require(\n (amount <= super.balanceOf(msg.sender, tokenId)),\n \"CLM8::retire: not enough available balance to retire\"\n );\n\n _retire(msg.sender, tokenId, amount);\n emit TokenRetired(msg.sender, tokenId, amount);\n }\n\n function _retire(\n address _address,\n uint256 tokenId,\n uint256 _quantity\n ) internal {\n super._burn(_address, tokenId, _quantity);\n _tokenDetails[tokenId].totalRetired = _tokenDetails[tokenId]\n .totalRetired\n .add(_quantity);\n _retiredBalances[tokenId][_address] = _retiredBalances[tokenId][\n _address\n ].add(_quantity);\n }\n\n /**\n * @dev returns true if Dealer's account is registered\n * @param account address of the dealer\n */\n function isDealerRegistered(address account) public view returns (bool) {\n if (\n hasRole(REGISTERED_REC_DEALER, account) ||\n hasRole(REGISTERED_OFFSET_DEALER, account) ||\n hasRole(REGISTERED_EMISSIONS_AUDITOR, account)\n ) return true;\n return false;\n }\n\n /**\n * @dev returns true if Consumers's account is registered\n * @param account address of the dealer\n */\n function isConsumerRegistered(address account) public view returns (bool) {\n return hasRole(REGISTERED_CONSUMER, account);\n }\n\n /**\n * @dev returns true if Consumers's or Dealer's account is registered\n * @param account address of the consumer/dealer\n */\n function isRegisteredDealerOrConsumer(address account)\n private\n view\n returns (bool)\n {\n return (isDealerRegistered(account) || isConsumerRegistered(account));\n }\n\n struct RolesInfo {\n bool isAdmin;\n bool isConsumer;\n bool isRecDealer;\n bool isCeoDealer;\n bool isAeDealer;\n bool isIndustry;\n }\n\n /**\n * @dev Helper function for returning tuple of bools of role membership\n * @param account address to check roles\n */\n function getRoles(address account)\n external\n view\n returns (RolesInfo memory)\n {\n RolesInfo memory roles;\n roles.isAdmin = hasRole(DEFAULT_ADMIN_ROLE, account);\n roles.isRecDealer = hasRole(REGISTERED_REC_DEALER, account);\n roles.isCeoDealer = hasRole(REGISTERED_OFFSET_DEALER, account);\n roles.isAeDealer = hasRole(REGISTERED_EMISSIONS_AUDITOR, account);\n roles.isIndustry = hasRole(REGISTERED_INDUSTRY, account);\n roles.isConsumer = hasRole(REGISTERED_CONSUMER, account);\n return roles;\n }\n\n /**\n * @dev Only contract owner can register Dealers\n * @param account address of the dealer to register\n */\n function registerDealer(address account, uint8 tokenTypeId)\n public\n onlyAdmin\n {\n require(\n tokenTypeIdIsValid(tokenTypeId),\n \"CLM8::registerDealer: tokenTypeId does not exist\"\n );\n if (tokenTypeId == 1) {\n grantRole(REGISTERED_REC_DEALER, account);\n } else if (tokenTypeId == 2) {\n grantRole(REGISTERED_OFFSET_DEALER, account);\n } else if (tokenTypeId == 3) {\n grantRole(REGISTERED_EMISSIONS_AUDITOR, account);\n }\n // Also grant generic dealer role for registering/unregistering dealer\n grantRole(REGISTERED_DEALER, account);\n emit RegisteredDealer(account);\n }\n\n /**\n * @dev msg.sender can volunteer themselves as registered industry\n * or other registered dealer can register Industry\n */\n function registerIndustry(address account) external {\n if (limitedMode) {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"CLM8::registerIndustry(limited): only admin can register industries\"\n );\n } else {\n _onlyDealer();\n }\n _setupRole(REGISTERED_INDUSTRY, account);\n emit RegisteredIndustry(account);\n }\n\n /**\n * @dev msg.sender can unvolunteer themselves as registered industry\n * or other registered dealer can unregister Industry\n */\n function unregisterIndustry(address account) external {\n if (msg.sender != account) {\n // only dealer can register industry\n _onlyDealer();\n }\n if (limitedMode) {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"CLM8::unregisterIndustry(limited): only admin can unregister industries\"\n );\n }\n revokeRole(REGISTERED_INDUSTRY, account);\n emit UnregisteredIndustry(account);\n }\n\n /**\n * @dev returns true if Consumer's account is registered for the given token\n * @param account address of the consumer\n */\n function registerConsumer(address account) external onlyDealer {\n if (limitedMode) {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"CLM8::registerConsumer(limited): only admin can register consumers\"\n );\n }\n grantRole(REGISTERED_CONSUMER, account);\n emit RegisteredConsumer(account);\n }\n\n /**\n * @dev Only contract owner can unregister Dealers\n * @param account address to be unregistered\n */\n function unregisterDealer(address account, uint8 tokenTypeId)\n external\n onlyAdmin\n {\n require(\n tokenTypeIdIsValid(tokenTypeId),\n \"CLM8::unregisterDealer: tokenTypeId does not exist\"\n );\n if (tokenTypeId == 1) {\n super.revokeRole(REGISTERED_REC_DEALER, account);\n } else if (tokenTypeId == 2) {\n super.revokeRole(REGISTERED_OFFSET_DEALER, account);\n } else if (tokenTypeId == 3) {\n super.revokeRole(REGISTERED_EMISSIONS_AUDITOR, account);\n }\n // If no longer a dealer of any token type, remove generic dealer role\n if (!isDealerRegistered(account)) {\n revokeRole(REGISTERED_DEALER, account);\n }\n\n emit UnregisteredDealer(account);\n }\n\n /**\n * @dev Only contract owner can unregister Consumers\n * TO-DO clarify the above - function allows any Dealer to unregister consumers.\n * Why would we need to unregister consumers?\n * @param account address to be unregistered\n */\n function unregisterConsumer(address account) external onlyDealer {\n if (limitedMode) {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"CLM8::unregisterConsumer(limited): only admin can unregister consumers\"\n );\n }\n super.revokeRole(REGISTERED_CONSUMER, account);\n emit UnregisteredConsumer(account);\n }\n\n /**\n * @dev transfers the value to the 'to' account for tokenId\n * @param to recipient address\n * @param tokenId tokenId for the transfer\n * @param value amount of transfer\n * Transfer can start only when both parties are registered and the token is not paused\n * Note: Token holders can arbitrarily call safeTransferFrom() without these checks\n * The requires commented out below have been moved to _beforeTokenTransfer hook\n * so that they are always applied to safeTransferFrom (or safeBatch...)\n */\n function transfer(\n address to,\n uint256 tokenId,\n uint256 value\n ) external {\n require(tokenExists(tokenId), \"CLM8::transfer: tokenId does not exist\");\n\n /*\n require((msg.sender != to), \"CLM8::transfer: sender and receiver cannot be the same\");\n receiver must be Consumer or Dealer or Industry\n require(\n hasRole(REGISTERED_CONSUMER, to) || \n hasRole(REGISTERED_DEALER, to) || \n hasRole(REGISTERED_INDUSTRY, to),\n \"CLM8::transfer: Recipient must be consumer, industry, or dealer\"\n ); */\n super.safeTransferFrom(msg.sender, to, tokenId, value, \"0x00\");\n }\n\n function setTimelock(address _timelock) external onlyAdmin {\n timelock = _timelock;\n }\n\n function getAvailableAndRetired(address account, uint256 tokenId)\n external\n view\n returns (uint256, uint256)\n {\n uint256 available = super.balanceOf(account, tokenId);\n uint256 retired = this.getTokenRetiredAmount(account, tokenId);\n return (available, retired);\n }\n\n /**\n * @dev returns issuer of a given tokenId\n */\n function getIssuedBy(uint256 tokenId) external view returns (address) {\n return _tokenDetails[tokenId].issuedBy;\n }\n\n /**\n * @dev returns issuer of a given tokenId\n */\n function getIssuedFrom(uint256 tokenId) external view returns (uint160) {\n return _tokenDetails[tokenId].issuedFrom;\n }\n\n /**\n * @dev returns the details of a given tokenId, omitting holders\n * @param tokenId token to check\n */\n function getTokenDetails(uint256 tokenId)\n external\n view\n returns (CarbonTokenDetails memory)\n {\n return _tokenDetails[tokenId];\n }\n\n /**\n * @dev turns off or on limited mode\n * @param _limitedMode boolean value\n */\n function setLimitedMode(bool _limitedMode) external onlyAdmin {\n limitedMode = _limitedMode;\n }\n\n function isAuditor(address auditor) external view returns (bool) {\n return hasRole(REGISTERED_EMISSIONS_AUDITOR, auditor);\n }\n\n function isIndustry(address industry) external view returns (bool) {\n return hasRole(REGISTERED_INDUSTRY, industry);\n }\n}\n" + }, + "solidity/Libraries/TxVerifier.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\n\nlibrary TxVerifier {\n using ECDSA for bytes32;\n using ECDSA for address;\n\n /**\n * @dev Returns `true` if transfer has been approved by to address\n * reconstruct transferHash and check that it matches the signature\n */\n function verifySignature(\n bytes32 msgHash,\n bytes memory signature,\n address signer\n ) internal pure returns (bool) {\n bytes32 ethSignedMessageHash = msgHash.toEthSignedMessageHash();\n return ethSignedMessageHash.recover(signature) == signer;\n }\n\n /**\n * @dev Returns keccak256 hash of transaction request\n * including next available nonce for transfer from -> to addresses\n */\n function _getTransferHash(\n address _from,\n address _to,\n uint256[] memory _ids,\n uint256[] memory _amounts,\n uint32 _nonce\n ) internal pure returns (bytes32) {\n return keccak256(abi.encode(_from, _to, _ids, _amounts, _nonce + 1));\n }\n\n /**\n * @dev Returns `true` if metadata signature is valid\n * (public functions are not broadcast to the EVM or blockchain network)\n */\n function verifyMetadataSignature(\n address contractAddress,\n uint256 productId,\n address signer,\n string memory metadata,\n bytes memory signature\n ) internal pure returns (bool) {\n //address signer = _tokenDetails[_productData[productId].tokenId].issuedBy;\n bytes32 ethSignedUnitHash = _getMetadataHash(\n contractAddress,\n productId,\n metadata\n ).toEthSignedMessageHash();\n return ethSignedUnitHash.recover(signature) == signer;\n }\n\n /**\n * @dev Returns keccak256 hash of text for a trackerId and productId pair\n * This function should be called by the auditor submitting product data\n * to produce a unitHash that is signed off-chain.\n * The signature can be provided to accounts requesting products\n * to verify the unit associated with product amounts\n * unit data is not stored on-chain to respect producer privacy\n */\n function _getMetadataHash(\n address contractAddress,\n uint256 productId,\n string memory metadata\n ) internal pure returns (bytes32) {\n return\n keccak256(abi.encodePacked(contractAddress, productId, metadata));\n }\n}\n" + }, + "solidity/Libraries/ArrayModifier.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nlibrary ArrayModifier {\n function updateIndex(\n uint256 id,\n uint256 amount,\n uint256[] storage ids,\n mapping(uint256 => uint256) storage idIndex\n ) internal {\n uint256 index = idIndex[id];\n if (amount > 0) {\n // if the final amount is positive check if the id should be added to the ids array\n if (index == 0) {\n ids.push(id);\n idIndex[id] = ids.length;\n }\n } else {\n if (index > 0) {\n if (ids.length > 1) {\n // first replace indexed id with last in ids array\n ids[index - 1] = ids[ids.length - 1];\n // 2nd updated the index of id we are deleting with the one replacing it\n idIndex[ids[index - 1]] = index;\n }\n // delete the index of the ud\n delete idIndex[id];\n // drop the last id from the array\n delete ids[ids.length - 1];\n }\n }\n }\n\n function updateIndexAndAmount(\n uint256 id,\n uint256 amount,\n uint256[] storage ids,\n mapping(uint256 => uint256) storage idIndex,\n mapping(uint256 => uint256) storage idAmount\n ) internal {\n updateIndex(id, amount, ids, idIndex);\n if (amount > 0) {\n idAmount[id] = amount;\n } else {\n delete idAmount[id];\n }\n }\n}\n" + }, + "solidity/Libraries/TrackerStructs.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\nimport \"../NetEmissionsTokenNetwork.sol\";\n\nlibrary Tracker {\n using SafeMath for uint256;\n\n /**\n * @dev tracker details\n * tokenId corresponding ERC1155 token ID\n * trackerId\n * trackee - address of the account the tracking will apply to\n * totalProductAmounts - to unit of products issued to this tracker\n **/\n struct CarbonTrackerDetails {\n uint256 tokenId;\n uint256 trackerId;\n address trackee;\n uint256 totalProductAmounts;\n }\n\n /**\n * @dev ProductDetails\n * tokenId corresponding ERC1155 token ID\n * trackerId that this product belongs to\n * amount of the product. used as a weighted amount (weight = amount/_trackerData.totalProductAmounts) to distribute a trackers total emissions across multiple products\n * available amount of product remaining for transfer\n **/\n struct ProductDetails {\n uint256 tokenId;\n uint256 productId;\n uint256 trackerId;\n uint256 issued;\n uint256 available;\n }\n\n /**\n * @dev tracker mappings\n * tokenIds - array of ids of NET (direct/indirect/offsets)\n * idIndex - mapping tokenId to its index in array. 1st index is 1, 0 reserved for unindexed\n * amount - mapping tokenId to amount of emissions\n * productIds - array of productIds tracked as inputs\n * productIdIndex mapping productId to index in array\n * productAmount - of productId tracked\n **/\n struct CarbonTrackerMappings {\n uint256[] tokenIds;\n mapping(uint256 => uint256) idIndex;\n mapping(uint256 => uint256) amount;\n uint256[] productIds;\n mapping(uint256 => uint256) productIdIndex;\n mapping(uint256 => uint256) productAmount;\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 && v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "solidity/Governance/Timelock.sol": { + "content": "pragma solidity ^0.8.0;\n// SPDX-License-Identifier: BSD-3-Clause\n\n/* Copyright 2021 Compound Labs, Inc.\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n3. Neither the name of the copyright holder nor the names of its contributors\nmay be used to endorse or promote products derived from this software without\nspecific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */\n\n// Original work from Compound: https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol\n// Modified to work in the NetEmissionsTokenNetwork system\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\ncontract Timelock {\n using SafeMath for uint256;\n\n event NewAdmin(address indexed newAdmin);\n event NewPendingAdmin(address indexed newPendingAdmin);\n event NewDelay(uint256 indexed newDelay);\n event CancelTransaction(\n bytes32 indexed txHash,\n address indexed target,\n uint256 value,\n string signature,\n bytes data,\n uint256 eta\n );\n event ExecuteTransaction(\n bytes32 indexed txHash,\n address indexed target,\n uint256 value,\n string signature,\n bytes data,\n uint256 eta\n );\n event QueueTransaction(\n bytes32 indexed txHash,\n address indexed target,\n uint256 value,\n string signature,\n bytes data,\n uint256 eta\n );\n\n uint256 public constant GRACE_PERIOD = 14 days;\n uint256 public constant MINIMUM_DELAY = 2 days;\n uint256 public constant MAXIMUM_DELAY = 30 days;\n\n address public admin;\n address public pendingAdmin;\n uint256 public delay;\n\n mapping(bytes32 => bool) public queuedTransactions;\n\n constructor(address admin_, uint256 delay_) {\n require(\n delay_ >= MINIMUM_DELAY,\n \"Timelock::constructor: Delay must exceed minimum delay.\"\n );\n require(\n delay_ <= MAXIMUM_DELAY,\n \"Timelock::setDelay: Delay must not exceed maximum delay.\"\n );\n\n admin = admin_;\n delay = delay_;\n }\n\n fallback() external payable {}\n\n receive() external payable {}\n\n function setDelay(uint256 delay_) public {\n require(\n msg.sender == address(this),\n \"Timelock::setDelay: Call must come from Timelock.\"\n );\n require(\n delay_ >= MINIMUM_DELAY,\n \"Timelock::setDelay: Delay must exceed minimum delay.\"\n );\n require(\n delay_ <= MAXIMUM_DELAY,\n \"Timelock::setDelay: Delay must not exceed maximum delay.\"\n );\n delay = delay_;\n\n emit NewDelay(delay);\n }\n\n function acceptAdmin() public {\n require(\n msg.sender == pendingAdmin,\n \"Timelock::acceptAdmin: Call must come from pendingAdmin.\"\n );\n admin = msg.sender;\n pendingAdmin = address(0);\n\n emit NewAdmin(admin);\n }\n\n function setPendingAdmin(address pendingAdmin_) public {\n require(\n msg.sender == address(this),\n \"Timelock::setPendingAdmin: Call must come from Timelock.\"\n );\n pendingAdmin = pendingAdmin_;\n\n emit NewPendingAdmin(pendingAdmin);\n }\n\n function queueTransaction(\n address target,\n uint256 value,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) public returns (bytes32) {\n require(\n msg.sender == admin,\n \"Timelock::queueTransaction: Call must come from admin.\"\n );\n require(\n eta >= getBlockTimestamp().add(delay),\n \"Timelock::queueTransaction: Estimated execution block must satisfy delay.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, value, signature, data, eta)\n );\n queuedTransactions[txHash] = true;\n\n emit QueueTransaction(txHash, target, value, signature, data, eta);\n return txHash;\n }\n\n function cancelTransaction(\n address target,\n uint256 value,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) public {\n require(\n msg.sender == admin,\n \"Timelock::cancelTransaction: Call must come from admin.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, value, signature, data, eta)\n );\n queuedTransactions[txHash] = false;\n\n emit CancelTransaction(txHash, target, value, signature, data, eta);\n }\n\n function executeTransaction(\n address target,\n uint256 value,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) public payable returns (bytes memory) {\n require(\n msg.sender == admin,\n \"Timelock::executeTransaction: Call must come from admin.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, value, signature, data, eta)\n );\n require(\n queuedTransactions[txHash],\n \"Timelock::executeTransaction: Transaction hasn't been queued.\"\n );\n require(\n getBlockTimestamp() >= eta,\n \"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\"\n );\n require(\n getBlockTimestamp() <= eta.add(GRACE_PERIOD),\n \"Timelock::executeTransaction: Transaction is stale.\"\n );\n\n queuedTransactions[txHash] = false;\n\n bytes memory callData;\n\n if (bytes(signature).length == 0) {\n callData = data;\n } else {\n callData = abi.encodePacked(\n bytes4(keccak256(bytes(signature))),\n data\n );\n }\n\n (bool success, bytes memory returnData) = target.call{value: value}(\n callData\n );\n require(\n success,\n \"Timelock::executeTransaction: Transaction execution reverted.\"\n );\n\n emit ExecuteTransaction(txHash, target, value, signature, data, eta);\n\n return returnData;\n }\n\n function getBlockTimestamp() internal view returns (uint256) {\n // solium-disable-next-line security/no-block-members\n return block.timestamp;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/hardhat/hardhat.config.ts b/hardhat/hardhat.config.ts index e5a8b35f2..9a223eb9f 100644 --- a/hardhat/hardhat.config.ts +++ b/hardhat/hardhat.config.ts @@ -15,6 +15,9 @@ import "hardhat-deploy-ethers"; import "@openzeppelin/hardhat-upgrades"; import "@ethersproject/bignumber"; +//import "@nomicfoundation/hardhat-toolbox"; +//import "@nomicfoundation/hardhat-chai-matchers"; +//import "@nomiclabs/hardhat-ethers"; import * as dotenv from 'dotenv' dotenv.config({path:'../.env'}) @@ -735,8 +738,8 @@ task("oilAndGasBenchmarkOperators","Use admin account to issue demo carbon track const db = await PostgresDBService.getInstance() // get latest trackerId - //let trackerId = await trackerContract.connect(await hre.ethers.getSigner(deployer)).getNumOfUniqueTrackers(); - let trackerId = 7 // previous completed tracker + let trackerId = await trackerContract.connect(await hre.ethers.getSigner(deployer)).getNumOfUniqueTrackers(); + // let trackerId = 7 // previous completed tracker const operators = ['Chevron','EnerVest Operating','Hilcorp Energy','ARD Operating','Apache','Noble Energy','EQT','Pioneer Natural Resources','Berry','Atlas Energy Group','Chesapeake Energy','CNX Resources','Devon Energy','Encana Oil & Gas','EXCO Resources','Breitburn Energy','ExxonMobil','ConocoPhillips','WPX Energy','EOG Resources','Scout Energy','Consol Energy','Occidental','BP','Total'] for (const operatorName of operators){ const operator = await db.getOperatorRepo().findByName(operatorName); @@ -1037,6 +1040,15 @@ module.exports = { runs: 200 } } + }, + { + version: "0.8.0", + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } } ] }, @@ -1047,10 +1059,23 @@ module.exports = { hardhat: { chainId: 1337 }, - ovm_localhost: { url: `http://localhost:9545` }, + // Uncomment the following lines if deploying contract to Hedera testnet + // Deploy with npx hardhat deploy --network hedera-testnet scripts/___.js + // "hedera-testnet": { + // //HashIO testnet endpoint from the TESTNET_ENDPOINT variable in the project .env the file + // url: ethereumConfig.HEDERA_TESTNET_ENDPOINT, + // chainId: 296, + // //the Hedera testnet account ECDSA private + // //the public address for the account is derived from the private key + // accounts: [ + // `${ethereumConfig.HEDERA_TESTNET_OPERATOR_PRIVATE_KEY}` + // ], + // gasPrice: 225000000000000, + // }, + // Deploy with npx hardhat --network hedera-testnet deploy --reset // Uncomment the following lines if deploying contract to Avalanche testnet // "avalanche-testnet": { @@ -1094,11 +1119,11 @@ module.exports = { // Uncomment the following lines if deploying contract to Goerli or running Etherscan verification // Deploy with npx hardhat run --network goerli scripts/___.js - // goerli: { - // url: `https://goerli.infura.io/v3/${ethereumConfig.INFURA_PROJECT_ID}`, - // accounts: [`0x${ethereumConfig.CONTRACT_OWNER_PRIVATE_KEY}`, - // `0x${ethereumConfig.OPERATOR_REGISTRY_PRIVATE_KEY}`,`0x${ethereumConfig.BUILDING_OWNER_PRIVATE_KEY}`] - // }, + //goerli: { + // url: `https://goerli.infura.io/v3/${ethereumConfig.INFURA_PROJECT_ID}`, + // accounts: [`0x${ethereumConfig.CONTRACT_OWNER_PRIVATE_KEY}`, + // `0x${ethereumConfig.OPERATOR_REGISTRY_PRIVATE_KEY}`,`0x${ethereumConfig.BUILDING_OWNER_PRIVATE_KEY}`] + //}, // Uncomment the following lines if deploying contract to xDai // Deploy with npx hardhat run --network xdai scripts/___.js diff --git a/hardhat/hedera/README.md b/hardhat/hedera/README.md index e9ec4c08c..e457ebe3f 100644 --- a/hardhat/hedera/README.md +++ b/hardhat/hedera/README.md @@ -4,53 +4,80 @@ Go to the [Hedera Portal](https://portal.hedera.com/register) to sign up for a Hedera testnet account. Once your sign up is successful, you will get a public key, private key, and testnet account ID. -Get a [Hedera wallet](https://hedera.com/buying-guide) If you've not used a Hedera wallet before, you can install the Hashpack browser plugin. Then, create an account, import your wallet, and enter the account ID and private key from your Hedera portal, and click on the "Testnet account" box. - Copy the file `.env.SAMPLE` to .`env` and fill in your testnet account ID and private key. +### Etherum Wallet Setup + +Thanks to the [Hedera JSON-RPC relay](https://docs.hedera.com/hedera/core-concepts/smart-contracts/json-rpc-relay) you can now connect to Hedera nodes using exisitng Ethereum tools like metamask. Here we explain how to use the [hashio community service](https://swirldslabs.com/hashio/). Alternatively, implement your own instance of the [open source relay](https://github.com/hashgraph/hedera-json-rpc-relay). + + +To import a Hedera network and add your private key generated above to metamask follow these (instructions)[https://hedera.com/blog/leveraging-ethereum-developer-tools-on-hedera#:~:text=over%20your%20account.-,Import,-Hedera%20Account%20into]. + +### Block explorer + + +Add the following block explorer to your wallet provider. [https://hashscan.io/](https://hashscan.io/) + +Another testnet blockscan is at https://testnet.dragonglass.me/hedera/home + +You can search, for example, for your contract ID to see it's been deployed. + +### Hedera wallet + +You can also interact with the network using a native [Hedera wallet](https://hedera.com/buying-guide). If you've not used a Hedera wallet before, you can install the Hashpack browser plugin. Thevn, create an account, import your wallet, and enter the account ID and private key from your Hedera portal, and click on the "Testnet account" box. + +*TODO*: + +The react-app UI needs to use HashConnect to connect to the Hedera wallet. See [Hashpack Hashconnect demo](https://github.com/Hashpack/hashconnect) + +*Recommend using [Ethereum Wallet Setup](#ethereum-wallet-setup) for metamask* + +[Mirror nodes](https://hedera.com/blog/how-to-look-up-transaction-history-on-hedera-using-mirror-nodes-back-to-the-basics) can be used to search transactions like GraphQL. + +See also reference [demo applications](https://docs.hedera.com/guides/resources/demo-applications) + + ## Deploying to Hedera +### Using hashgraph SDK + +We can deploy the contracts using the [@hashgraph/sdk](https://github.com/hashgraph/hedera-sdk-js). See [Deploy Your First Contract](https://docs.hedera.com/hedera/tutorials/smart-contracts/deploy-your-first-smart-contract#3.-deploy-a-hedera-smart-contract) for background. + Install the dependencies in this directory ``` npm install ``` -Then run the deploy script +Run the deploy script to add the NetEmissionsToken and Carbon Tracker contract to the hedera testnet. +*TODO: include DAOToken, Timelock and Governon contracts* ``` $ node deploy.js +Deploy NetEmissionsTokenNetwork contract Chunk 0 added. The smart contract bytecode file ID is 0.0.34117678 Processing chunk 1 Chunk 1 appended with status SUCCESS Processing chunk 2 Chunk 2 appended with status SUCCESS -Processing chunk 3 -Chunk 3 appended with status SUCCESS -Processing chunk 4 -Chunk 4 appended with status SUCCESS -Processing chunk 5 -Chunk 5 appended with status SUCCESS -Processing chunk 6 -Chunk 6 appended with status SUCCESS -Processing chunk 7 -Chunk 7 appended with status SUCCESS -Processing chunk 8 -Chunk 8 appended with status SUCCESS -The smart contract ID is 0.0.34117679 -The smart contract Solidity address is 000000000000000000000000000000000208982f -``` - -## Block Explorer +... -The testnet blockscan is at https://testnet.dragonglass.me/hedera/home - -You can search, for example, for your contract ID to see it's been deployed. +The smart contract ID is 0.0.xxxxxxxx +The smart contract Solidity address is 000000000000000000000000000000000xxxxxxx +Deploy CarbonTracker contract +Chunk 0 added. The smart contract bytecode file ID is 0.0.34117678 +Processing chunk 1 +Chunk 1 appended with status SUCCESS +Processing chunk 2 +Chunk 2 appended with status SUCCESS +... -## TODO +The smart contract ID is 0.0.xxxxxxxx +The smart contract Solidity address is 000000000000000000000000000000000xxxxxxx +``` -The react-app UI needs to use HashConnect to connect to the Hedera wallet. See [Hashpack Hashconnect demo](https://github.com/Hashpack/hashconnect) +## Hardhat deploy -[Mirror nodes](https://hedera.com/blog/how-to-look-up-transaction-history-on-hedera-using-mirror-nodes-back-to-the-basics) can be used to search transactions like GraphQL. +The [Hedera JSON-RPC relay](https://docs.hedera.com/hedera/core-concepts/smart-contracts/json-rpc-relay) can also be used to deploy the contract using Hardhat. -See also reference [demo applications](https://docs.hedera.com/guides/resources/demo-applications) \ No newline at end of file +However, this community relay fails to deploy larger contracts becasue of gas fee throttling. diff --git a/hardhat/hedera/deploy.js b/hardhat/hedera/deploy.js index 477bd9ecd..7f25f5573 100644 --- a/hardhat/hedera/deploy.js +++ b/hardhat/hedera/deploy.js @@ -1,4 +1,7 @@ -const { Client, ContractCreateTransaction, FileCreateTransaction, FileAppendTransaction, PrivateKey} = require("@hashgraph/sdk"); +const { + Client, PrivateKey, AccountId, + ContractCreateTransaction, ContractFunctionParameters, + FileCreateTransaction, FileAppendTransaction } = require("@hashgraph/sdk"); require("dotenv").config(); string_chop = function(str, size){ @@ -11,8 +14,10 @@ return size > 0 ? str.match(new RegExp('.{1,' + size + '}', 'g')) : [str]; async function main() { //Grab your Hedera testnet account ID and private key from your .env file -const myAccountId = process.env.MY_ACCOUNT_ID; -const myPrivateKey = process.env.MY_PRIVATE_KEY; +const myAccountId = //AccountId.fromString( + process.env.MY_ACCOUNT_ID; +const myPrivateKey = //PrivateKey.fromString( + process.env.MY_PRIVATE_KEY; // If we weren't able to grab it, we should throw a new error if (myAccountId == null || @@ -26,67 +31,103 @@ const client = Client.forTestnet(); client.setOperator(myAccountId, myPrivateKey); -let NetEmissionsTokens = require("../../artifacts/contracts/NetEmissionsTokenNetwork.sol/NetEmissionsTokenNetwork.json"); -const bytecode = NetEmissionsTokens.bytecode; - -// Hedera files have a limit of 6 KB so we must chop the bytecode down -bytecode_arr = string_chop(bytecode,5000); -chunks = bytecode_arr.length; - -//Create a file on Hedera and store the hex-encoded bytecode -// must set the array of keys which have access to the file or the Append later will get UNAUTHORIZED error -const fileCreateTx = new FileCreateTransaction() - .setKeys([PrivateKey.fromString(myPrivateKey)]) - .setContents(bytecode_arr[0]); - -//Submit the file to the Hedera test network signing with the transaction fee payer key specified with the client -const submitTx = await fileCreateTx.execute(client); - -//Get the receipt of the file create transaction -const fileReceipt = await submitTx.getReceipt(client); - -//Get the file ID from the receipt -const bytecodeFileId = fileReceipt.fileId; - -//Log the file ID -console.log("Chunk 0 added. The smart contract bytecode file ID is " +bytecodeFileId); - -// now append all the chunks of the bytecode -for (let i = 1; i < chunks; i++) { - console.log("Processing chunk " + i); - // append the next chunk. Must use freezeWith or will get a "transaction must have been frozen before calculating the hash will be stable" error - const fileAppendTx = new FileAppendTransaction() - .setFileId(bytecodeFileId) - .setContents(bytecode_arr[i]) - .freezeWith(client); - // sign with one of the keys from FileCreateTransaction.setKeys - fileAppendTx.sign(PrivateKey.fromString(myPrivateKey)); - const appendTx = await fileAppendTx.execute(client); - const appendReceipt = await appendTx.getReceipt(client); - console.log("Chunk " + i + " appended with status " + appendReceipt.status.toString()); -} +/* +TO-DO deploy daoToken, timelock and governor contracts and excecute functions + +console.log("Deploy Timelock contract"); +let Timelock = require("../artifacts/solidity/Governance/Timelock.sol/Timelock.json"); +let bytecode = Timelock.bytecode; +let fnParameters = new ContractFunctionParameters() + .addAddress(process.env.PUBLIC_EVM_ADDRESS) + .addUint256(172800); -//Deploy the contract instance -const contractTx = await new ContractCreateTransaction() - //The bytecode file ID - .setBytecodeFileId(bytecodeFileId) - //The max gas to reserve - .setGas(2000000); +timelockAddress = await createContract(bytecode,client,myPrivateKey,fnParameters); -//Submit the transaction to the Hedera test network -const contractResponse = await contractTx.execute(client); +*/ -//Get the receipt of the file create transaction -const contractReceipt = await contractResponse.getReceipt(client); +console.log("Deploy NetEmissionsTokenNetwork contract"); +let NetEmissionsTokens = require("../artifacts/solidity/NetEmissionsTokenNetwork.sol/NetEmissionsTokenNetwork.json"); +let bytecode = NetEmissionsTokens.bytecode; +let netAddress; +let fnParameters = new ContractFunctionParameters().addAddress(process.env.PUBLIC_EVM_ADDRESS); +netAddress = await createContract(bytecode,client,myPrivateKey,fnParameters); -//Get the smart contract ID -const newContractId = contractReceipt.contractId; +//if(process.env.NET_ADDRESS){netAddress=process.env.NET_ADDRESS;} -const newContractAddress = newContractId.toSolidityAddress(); +console.log("Deploy CarbonTracker contract"); +let CarbonTracker = require("../artifacts/solidity/CarbonTracker.sol/CarbonTracker.json"); +bytecode = CarbonTracker.bytecode; + +fnParameters = new ContractFunctionParameters() + .addAddress(process.env.PUBLIC_EVM_ADDRESS) + .addAddress(netAddress); +console.log(fnParameters) +await createContract(bytecode,client,myPrivateKey,fnParameters); -//Log the smart contract ID -console.log("The smart contract ID is " + newContractId); -console.log("The smart contract Solidity address is " + newContractAddress); } +async function createContract(bytecode, client, myPrivateKey,fnParameters){ + // Hedera files have a limit of 6 KB so we must chop the bytecode down + bytecode_arr = string_chop(bytecode,5000); + chunks = bytecode_arr.length; + + //Create a file on Hedera and store the hex-encoded bytecode + // must set the array of keys which have access to the file or the Append later will get UNAUTHORIZED error + const fileCreateTx = new FileCreateTransaction() + .setKeys([PrivateKey.fromString(myPrivateKey)]) + .setContents(bytecode_arr[0]); + + + //Submit the file to the Hedera test network signing with the transaction fee payer key specified with the client + const submitTx = await fileCreateTx.execute(client); + + //Get the receipt of the file create transaction + const fileReceipt = await submitTx.getReceipt(client); + + //Get the file ID from the receipt + const bytecodeFileId = fileReceipt.fileId; + + //Log the file ID + console.log("Chunk 0 added. The smart contract bytecode file ID is " +bytecodeFileId); + + // now append all the chunks of the bytecode + for (let i = 1; i < chunks; i++) { + console.log("Processing chunk " + i); + // append the next chunk. Must use freezeWith or will get a "transaction must have been frozen before calculating the hash will be stable" error + const fileAppendTx = new FileAppendTransaction() + .setFileId(bytecodeFileId) + .setContents(bytecode_arr[i]) + .freezeWith(client); + // sign with one of the keys from FileCreateTransaction.setKeys + fileAppendTx.sign(PrivateKey.fromString(myPrivateKey)); + const appendTx = await fileAppendTx.execute(client); + const appendReceipt = await appendTx.getReceipt(client); + console.log("Chunk " + i + " appended with status " + appendReceipt.status.toString()); + } + //Deploy the contract instance + const contractTx = await new ContractCreateTransaction() + //The bytecode file ID + .setBytecodeFileId(bytecodeFileId) + //The max gas to reserve + .setGas(2000000) + //Provide the constructor parameters for the contract + .setConstructorParameters(fnParameters) + ; + + //Submit the transaction to the Hedera test network + const contractResponse = await contractTx.execute(client); + + //Get the receipt of the file create transaction + const contractReceipt = await contractResponse.getReceipt(client); + + //Get the smart contract ID + const newContractId = contractReceipt.contractId; + + const newContractAddress = newContractId.toSolidityAddress(); + + //Log the smart contract ID + console.log("The smart contract ID is " + newContractId); + console.log("The smart contract Solidity address is " + newContractAddress); + return newContractAddress; +} main(); \ No newline at end of file diff --git a/hardhat/hedera/package-lock.json b/hardhat/hedera/package-lock.json new file mode 100644 index 000000000..694c28422 --- /dev/null +++ b/hardhat/hedera/package-lock.json @@ -0,0 +1,1278 @@ +{ + "name": "net-emissions-token-network-hedera", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "net-emissions-token-network-hedera", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@hashgraph/sdk": "^2.11.3", + "dotenv": "^16.0.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ] + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.8.13", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.13.tgz", + "integrity": "sha512-iY3jsdfbc0ARoCLFvbvUB8optgyb0r1XLPb142u+QtgBcKJYkCIFt3Fd/881KqjLYWjsBJF57N3b8Eop9NDfUA==", + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.6.tgz", + "integrity": "sha512-QyAXR8Hyh7uMDmveWxDSUcJr9NAWaZ2I6IXgAYvQmfflwouTM+rArE2eEaCtLlRqO81j7pRLCt81IefUei6Zbw==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^7.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@hashgraph/cryptography": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.4.3.tgz", + "integrity": "sha512-txU2SVz8mBJ5aHqkrIpmaerJSu0F/S9T/0eXpYAIC2USy/8oTisp54gKVDTETFdnCrq0tNgCJmWt2N8QHMMbcw==", + "dependencies": { + "bignumber.js": "^9.1.1", + "crypto-js": "^4.1.1", + "elliptic": "^6.5.4", + "js-base64": "^3.7.4", + "tweetnacl": "^1.0.3", + "utf8": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "expo": "^45.0.3", + "expo-crypto": "^10.1.2", + "expo-random": "^12.1.2" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + }, + "expo-crypto": { + "optional": true + }, + "expo-random": { + "optional": true + } + } + }, + "node_modules/@hashgraph/proto": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@hashgraph/proto/-/proto-2.12.0.tgz", + "integrity": "sha512-IIN6K3b2X8ih7V14IDH8rsVJ1DE9ud25FfKUpr+lDNnQdBfdZdG2AGlHRhc9iDAz4vCHoHc6F3Ao6yYKMceeTg==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "^7.1.2", + "protobufjs-cli": "^1.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@hashgraph/sdk": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/@hashgraph/sdk/-/sdk-2.23.0.tgz", + "integrity": "sha512-P/hv/mz1vmNLvQxtSzE6ptHaqmtDJtmM69FhJPEYf8fBklSPPWnBrA/jYEHm2lNSZwM1HyODEWcNfV+h44iA6w==", + "dependencies": { + "@ethersproject/rlp": "^5.7.0", + "@grpc/grpc-js": "^1.7.3", + "@hashgraph/cryptography": "^1.4.3", + "@hashgraph/proto": "2.12.0", + "axios": "^1.3.1", + "bignumber.js": "^9.1.1", + "crypto-js": "^4.1.1", + "js-base64": "^3.7.4", + "js-logger": "^1.6.1", + "long": "^4.0.0", + "protobufjs": "^7.1.2", + "utf8": "^3.0.0" + }, + "engines": { + "node": ">=10.17.0" + }, + "peerDependencies": { + "expo": "^45.0.3" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + } + } + }, + "node_modules/@jsdoc/salty": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", + "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==" + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==" + }, + "node_modules/@types/node": { + "version": "18.15.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz", + "integrity": "sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==" + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bignumber.js": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "engines": { + "node": "*" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/espree": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/js-base64": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", + "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + }, + "node_modules/js-logger": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/js-logger/-/js-logger-1.6.1.tgz", + "integrity": "sha512-yTgMCPXVjhmg28CuUH8CKjU+cIKL/G+zTu4Fn4lQxs8mRFH/03QTNvEFngcxfg/gRDiQAOoyCKmMTOm9ayOzXA==" + }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/protobufjs": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.2.tgz", + "integrity": "sha512-++PrQIjrom+bFDPpfmqXfAGSQs40116JRrqqyf53dymUMvvb5d/LMRyicRoF1AUKoXVS1/IgJXlEgcpr4gTF3Q==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/protobufjs-cli": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz", + "integrity": "sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA==", + "dependencies": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "protobufjs": "^7.0.0" + } + }, + "node_modules/protobufjs/node_modules/long": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", + "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + } + } +}